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.
22 #define IN_RECT(r,x,y) \
44 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
46 POINTL SourcePoint
, BrushOrigin
;
48 XLATEOBJ
*XlateObj
= NULL
;
49 HPALETTE SourcePalette
= 0, DestPalette
= 0;
50 PGDIBRUSHOBJ BrushObj
;
51 GDIBRUSHINST BrushInst
;
52 BOOL UsesSource
= ROP_USES_SOURCE(ROP
);
53 BOOL UsesPattern
= ROP_USES_PATTERN(ROP
);
55 DCDest
= DC_LockDc(hDCDest
);
58 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest
);
59 SetLastWin32Error(ERROR_INVALID_HANDLE
);
65 if (hDCSrc
!= hDCDest
)
67 DCSrc
= DC_LockDc(hDCSrc
);
71 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc
);
72 SetLastWin32Error(ERROR_INVALID_HANDLE
);
86 /* Offset the destination and source by the origin of their DCs. */
87 XDest
+= DCDest
->w
.DCOrgX
;
88 YDest
+= DCDest
->w
.DCOrgY
;
91 XSrc
+= DCSrc
->w
.DCOrgX
;
92 YSrc
+= DCSrc
->w
.DCOrgY
;
95 DestRect
.left
= XDest
;
97 DestRect
.right
= XDest
+Width
;
98 DestRect
.bottom
= YDest
+Height
;
100 SourcePoint
.x
= XSrc
;
101 SourcePoint
.y
= YSrc
;
106 /* Determine surfaces to be used in the bitblt */
107 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
110 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
111 BitmapSrc
= BitmapDest
;
113 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
122 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
123 if (NULL
== BrushObj
)
125 if (UsesSource
&& hDCSrc
!= hDCDest
)
129 if(BitmapDest
!= NULL
)
131 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
133 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
135 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
137 DC_UnlockDc(hDCDest
);
138 SetLastWin32Error(ERROR_INVALID_HANDLE
);
141 BrushOrigin
= BrushObj
->ptOrigin
;
142 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, DCDest
->XlateBrush
);
149 /* Create the XLATEOBJ. */
152 if (DCDest
->w
.hPalette
!= 0)
153 DestPalette
= DCDest
->w
.hPalette
;
155 if (DCSrc
->w
.hPalette
!= 0)
156 SourcePalette
= DCSrc
->w
.hPalette
;
158 /* KB41464 details how to convert between mono and color */
159 if (DCDest
->w
.bitsPerPixel
== 1 && DCSrc
->w
.bitsPerPixel
== 1)
165 if (DCDest
->w
.bitsPerPixel
== 1)
167 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
169 else if (DCSrc
->w
.bitsPerPixel
== 1)
171 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
175 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
177 if (NULL
== XlateObj
)
179 if (UsesSource
&& hDCSrc
!= hDCDest
)
183 DC_UnlockDc(hDCDest
);
184 if(BitmapDest
!= NULL
)
186 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
188 if(BitmapSrc
!= NULL
&& BitmapSrc
!= BitmapDest
)
190 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
194 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
196 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
202 /* Perform the bitblt operation */
203 Status
= IntEngBitBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
204 &DestRect
, &SourcePoint
, NULL
, BrushObj
? &BrushInst
.BrushObject
: NULL
, &BrushOrigin
, ROP
);
206 if (UsesSource
&& XlateObj
!= NULL
)
207 EngDeleteXlate(XlateObj
);
209 if(BitmapDest
!= NULL
)
211 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
213 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
215 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
217 if (BrushObj
!= NULL
)
219 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
221 if (UsesSource
&& hDCSrc
!= hDCDest
)
225 DC_UnlockDc(hDCDest
);
246 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
248 HPALETTE SourcePalette
= 0, DestPalette
= 0;
249 PPALGDI PalDestGDI
, PalSourceGDI
;
250 USHORT PalDestMode
, PalSrcMode
;
251 ULONG TransparentColor
= 0;
254 if(!(DCDest
= DC_LockDc(hdcDst
)))
256 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
257 SetLastWin32Error(ERROR_INVALID_HANDLE
);
261 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
264 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
265 SetLastWin32Error(ERROR_INVALID_HANDLE
);
273 /* Offset positions */
274 xDst
+= DCDest
->w
.DCOrgX
;
275 yDst
+= DCDest
->w
.DCOrgY
;
276 xSrc
+= DCSrc
->w
.DCOrgX
;
277 ySrc
+= DCSrc
->w
.DCOrgY
;
279 if(DCDest
->w
.hPalette
)
280 DestPalette
= DCDest
->w
.hPalette
;
282 if(DCSrc
->w
.hPalette
)
283 SourcePalette
= DCSrc
->w
.hPalette
;
285 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
289 SetLastWin32Error(ERROR_INVALID_HANDLE
);
292 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
294 PALETTE_UnlockPalette(SourcePalette
);
297 SetLastWin32Error(ERROR_INVALID_HANDLE
);
300 if(DestPalette
!= SourcePalette
)
302 PalDestMode
= PalDestGDI
->Mode
;
303 PalSrcMode
= PalSourceGDI
->Mode
;
304 PALETTE_UnlockPalette(DestPalette
);
308 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
310 PALETTE_UnlockPalette(SourcePalette
);
312 /* Translate Transparent (RGB) Color to the source palette */
313 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
315 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
316 EngDeleteXlate(XlateObj
);
319 /* Create the XLATE object to convert colors between source and destination */
320 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
322 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
323 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
325 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
326 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
331 rcDest
.right
= rcDest
.left
+ cxDst
;
332 rcDest
.bottom
= rcDest
.top
+ cyDst
;
335 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
336 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
338 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
340 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
344 Ret
= IntEngTransparentBlt(BitmapDest
, BitmapSrc
, DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
345 TransparentColor
, 0);
348 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
349 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
357 EngDeleteXlate(XlateObj
);
374 /* NOTE: Windows also doesn't store nr. of planes separately! */
375 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
377 /* Check parameters */
378 if (!Height
|| !Width
)
380 Size
.cx
= Size
.cy
= 1;
384 Size
.cx
= abs(Width
);
385 Size
.cy
= abs(Height
);
388 /* Create the bitmap object. */
389 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
390 BitmapFormat(BitsPerPel
, BI_RGB
),
391 (Height
< 0 ? BMF_TOPDOWN
: 0) |
392 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
395 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
399 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
400 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
402 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
403 /* FIXME - bmp can be NULL!!!!!! */
404 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
405 BITMAPOBJ_UnlockBitmap( hBitmap
);
408 * NOTE: It's ugly practice, but we are using the object even
409 * after unlocking. Since the handle is currently known only
410 * to us it should be safe.
415 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
422 BITMAP_Cleanup(PVOID ObjectBody
)
424 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
425 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
426 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
428 if (pBmp
->dib
== NULL
)
430 ExFreePool(pBmp
->SurfObj
.pvBits
);
434 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
443 IntCreateCompatibleBitmap(
452 if ((Width
>= 0x10000) || (Height
>= 0x10000))
454 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
458 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
459 if (0 == Width
|| 0 == Height
)
461 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
465 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
472 NtGdiCreateCompatibleBitmap(
482 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
486 SetLastWin32Error(ERROR_INVALID_HANDLE
);
490 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
492 DPRINT ("\t\t%04x\n", Bmp
);
498 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
500 return NtGdiCreateBitmap (BM
->bmWidth
,
508 NtGdiCreateDiscardableBitmap(
513 /* FIXME: this probably should do something else */
514 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
536 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
540 NtGdiGetBitmapDimensionEx(
546 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
552 *Dimension
= bmp
->dimension
;
554 BITMAPOBJ_UnlockBitmap(hBitmap
);
560 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
563 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
564 BOOL bInRect
= FALSE
;
565 BITMAPOBJ
*BitmapObject
;
566 SURFOBJ
*SurfaceObject
;
570 dc
= DC_LockDc (hDC
);
574 SetLastWin32Error(ERROR_INVALID_HANDLE
);
577 XPos
+= dc
->w
.DCOrgX
;
578 YPos
+= dc
->w
.DCOrgY
;
579 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
582 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
583 SurfaceObject
= &BitmapObject
->SurfObj
;
586 if ( dc
->w
.hPalette
!= 0 )
587 Pal
= dc
->w
.hPalette
;
588 /* FIXME: Verify if it shouldn't be PAL_BGR! */
589 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
592 // check if this DC has a DIB behind it...
593 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
595 ASSERT ( SurfaceObject
->lDelta
);
596 Result
= XLATEOBJ_iXlate(XlateObj
,
597 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
599 EngDeleteXlate(XlateObj
);
601 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
606 // if Result is still CLR_INVALID, then the "quick" method above didn't work
607 if ( bInRect
&& Result
== CLR_INVALID
)
609 // FIXME: create a 1x1 32BPP DIB, and blit to it
610 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
613 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
615 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
616 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
617 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
620 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
625 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
626 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
628 // our bitmap is no longer selected, so we can access it's stuff...
629 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
632 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
633 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
636 NtGdiDeleteObject ( hBmpTmp
);
638 NtGdiDeleteDC ( hDCTmp
);
645 /***********************************************************************
647 * Ported from WINE by sedwards 11-4-03
649 * Someone thought it would be faster to do it here and then switch back
650 * to GDI32. I dunno. Write a test and let me know.
654 SwapROP3_SrcDst(BYTE bRop3
)
656 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
659 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
660 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
661 #define DSTCOPY 0x00AA0029
662 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
666 HDC hdcDest
, INT nXDest
, INT nYDest
,
667 INT nWidth
, INT nHeight
, HDC hdcSrc
,
668 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
669 INT xMask
, INT yMask
, DWORD dwRop
)
671 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
672 HDC hDCMask
, hDC1
, hDC2
;
673 static const DWORD ROP3Table
[256] =
675 0x00000042, 0x00010289,
676 0x00020C89, 0x000300AA,
677 0x00040C88, 0x000500A9,
678 0x00060865, 0x000702C5,
679 0x00080F08, 0x00090245,
680 0x000A0329, 0x000B0B2A,
681 0x000C0324, 0x000D0B25,
682 0x000E08A5, 0x000F0001,
683 0x00100C85, 0x001100A6,
684 0x00120868, 0x001302C8,
685 0x00140869, 0x001502C9,
686 0x00165CCA, 0x00171D54,
687 0x00180D59, 0x00191CC8,
688 0x001A06C5, 0x001B0768,
689 0x001C06CA, 0x001D0766,
690 0x001E01A5, 0x001F0385,
691 0x00200F09, 0x00210248,
692 0x00220326, 0x00230B24,
693 0x00240D55, 0x00251CC5,
694 0x002606C8, 0x00271868,
695 0x00280369, 0x002916CA,
696 0x002A0CC9, 0x002B1D58,
697 0x002C0784, 0x002D060A,
698 0x002E064A, 0x002F0E2A,
699 0x0030032A, 0x00310B28,
700 0x00320688, 0x00330008,
701 0x003406C4, 0x00351864,
702 0x003601A8, 0x00370388,
703 0x0038078A, 0x00390604,
704 0x003A0644, 0x003B0E24,
705 0x003C004A, 0x003D18A4,
706 0x003E1B24, 0x003F00EA,
707 0x00400F0A, 0x00410249,
708 0x00420D5D, 0x00431CC4,
709 0x00440328, 0x00450B29,
710 0x004606C6, 0x0047076A,
711 0x00480368, 0x004916C5,
712 0x004A0789, 0x004B0605,
713 0x004C0CC8, 0x004D1954,
714 0x004E0645, 0x004F0E25,
715 0x00500325, 0x00510B26,
716 0x005206C9, 0x00530764,
717 0x005408A9, 0x00550009,
718 0x005601A9, 0x00570389,
719 0x00580785, 0x00590609,
720 0x005A0049, 0x005B18A9,
721 0x005C0649, 0x005D0E29,
722 0x005E1B29, 0x005F00E9,
723 0x00600365, 0x006116C6,
724 0x00620786, 0x00630608,
725 0x00640788, 0x00650606,
726 0x00660046, 0x006718A8,
727 0x006858A6, 0x00690145,
728 0x006A01E9, 0x006B178A,
729 0x006C01E8, 0x006D1785,
730 0x006E1E28, 0x006F0C65,
731 0x00700CC5, 0x00711D5C,
732 0x00720648, 0x00730E28,
733 0x00740646, 0x00750E26,
734 0x00761B28, 0x007700E6,
735 0x007801E5, 0x00791786,
736 0x007A1E29, 0x007B0C68,
737 0x007C1E24, 0x007D0C69,
738 0x007E0955, 0x007F03C9,
739 0x008003E9, 0x00810975,
740 0x00820C49, 0x00831E04,
741 0x00840C48, 0x00851E05,
742 0x008617A6, 0x008701C5,
743 0x008800C6, 0x00891B08,
744 0x008A0E06, 0x008B0666,
745 0x008C0E08, 0x008D0668,
746 0x008E1D7C, 0x008F0CE5,
747 0x00900C45, 0x00911E08,
748 0x009217A9, 0x009301C4,
749 0x009417AA, 0x009501C9,
750 0x00960169, 0x0097588A,
751 0x00981888, 0x00990066,
752 0x009A0709, 0x009B07A8,
753 0x009C0704, 0x009D07A6,
754 0x009E16E6, 0x009F0345,
755 0x00A000C9, 0x00A11B05,
756 0x00A20E09, 0x00A30669,
757 0x00A41885, 0x00A50065,
758 0x00A60706, 0x00A707A5,
759 0x00A803A9, 0x00A90189,
760 0x00AA0029, 0x00AB0889,
761 0x00AC0744, 0x00AD06E9,
762 0x00AE0B06, 0x00AF0229,
763 0x00B00E05, 0x00B10665,
764 0x00B21974, 0x00B30CE8,
765 0x00B4070A, 0x00B507A9,
766 0x00B616E9, 0x00B70348,
767 0x00B8074A, 0x00B906E6,
768 0x00BA0B09, 0x00BB0226,
769 0x00BC1CE4, 0x00BD0D7D,
770 0x00BE0269, 0x00BF08C9,
771 0x00C000CA, 0x00C11B04,
772 0x00C21884, 0x00C3006A,
773 0x00C40E04, 0x00C50664,
774 0x00C60708, 0x00C707AA,
775 0x00C803A8, 0x00C90184,
776 0x00CA0749, 0x00CB06E4,
777 0x00CC0020, 0x00CD0888,
778 0x00CE0B08, 0x00CF0224,
779 0x00D00E0A, 0x00D1066A,
780 0x00D20705, 0x00D307A4,
781 0x00D41D78, 0x00D50CE9,
782 0x00D616EA, 0x00D70349,
783 0x00D80745, 0x00D906E8,
784 0x00DA1CE9, 0x00DB0D75,
785 0x00DC0B04, 0x00DD0228,
786 0x00DE0268, 0x00DF08C8,
787 0x00E003A5, 0x00E10185,
788 0x00E20746, 0x00E306EA,
789 0x00E40748, 0x00E506E5,
790 0x00E61CE8, 0x00E70D79,
791 0x00E81D74, 0x00E95CE6,
792 0x00EA02E9, 0x00EB0849,
793 0x00EC02E8, 0x00ED0848,
794 0x00EE0086, 0x00EF0A08,
795 0x00F00021, 0x00F10885,
796 0x00F20B05, 0x00F3022A,
797 0x00F40B0A, 0x00F50225,
798 0x00F60265, 0x00F708C5,
799 0x00F802E5, 0x00F90845,
800 0x00FA0089, 0x00FB0A09,
801 0x00FC008A, 0x00FD0A0A,
802 0x00FE02A9, 0x00FF0062,
806 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
808 /* 1. make mask bitmap's dc */
809 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
810 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
812 /* 2. make masked Background bitmap */
814 /* 2.1 make bitmap */
815 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
816 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
817 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
819 /* 2.2 draw dest bitmap and mask */
820 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
821 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
822 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
824 /* 3. make masked Foreground bitmap */
826 /* 3.1 make bitmap */
827 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
828 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
829 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
831 /* 3.2 draw src bitmap and mask */
832 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
833 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
834 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
836 /* 4. combine two bitmap and copy it to hdcDest */
837 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
838 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
840 /* 5. restore all object */
841 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
842 NtGdiSelectObject(hDC1
, hOldBitmap2
);
843 NtGdiSelectObject(hDC2
, hOldBitmap3
);
845 /* 6. delete all temp object */
846 NtGdiDeleteObject(hBitmap2
);
847 NtGdiDeleteObject(hBitmap3
);
851 NtGdiDeleteDC(hDCMask
);
882 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
883 if (bmp
== NULL
|| Bits
== NULL
)
890 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
894 /* Only get entire lines */
895 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
896 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
898 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
900 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
901 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
905 bmp
->SurfObj
.sizlBitmap
.cx
,
906 bmp
->SurfObj
.sizlBitmap
.cy
,
907 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
911 /* FIXME: call DDI specific function here if available */
914 DPRINT ("Calling device specific BitmapBits\n");
915 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
917 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
921 DPRINT ("BitmapBits == NULL??\n");
928 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
932 BITMAPOBJ_UnlockBitmap(hBitmap
);
938 NtGdiSetBitmapDimensionEx(
946 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
954 *Size
= bmp
->dimension
;
956 bmp
->dimension
.cx
= Width
;
957 bmp
->dimension
.cy
= Height
;
959 BITMAPOBJ_UnlockBitmap (hBitmap
);
971 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
972 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
976 return ((COLORREF
) -1);
986 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
989 if (NewBrush
== NULL
)
991 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
992 if (OldBrush
== NULL
)
994 NtGdiDeleteObject(NewBrush
);
997 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
998 NtGdiSelectObject(hDC
, OldBrush
);
999 NtGdiDeleteObject(NewBrush
);
1019 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1023 XLATEOBJ
*XlateObj
= NULL
;
1024 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1025 PGDIBRUSHOBJ BrushObj
;
1026 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1027 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1029 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1031 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1034 DCDest
= DC_LockDc(hDCDest
);
1037 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1038 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1044 if (hDCSrc
!= hDCDest
)
1046 DCSrc
= DC_LockDc(hDCSrc
);
1049 DC_UnlockDc(hDCDest
);
1050 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1051 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1065 /* Offset the destination and source by the origin of their DCs. */
1066 XOriginDest
+= DCDest
->w
.DCOrgX
;
1067 YOriginDest
+= DCDest
->w
.DCOrgY
;
1070 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1071 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1074 DestRect
.left
= XOriginDest
;
1075 DestRect
.top
= YOriginDest
;
1076 DestRect
.right
= XOriginDest
+WidthDest
;
1077 DestRect
.bottom
= YOriginDest
+HeightDest
;
1079 SourceRect
.left
= XOriginSrc
;
1080 SourceRect
.top
= YOriginSrc
;
1081 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1082 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1084 /* Determine surfaces to be used in the bitblt */
1085 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1088 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1089 BitmapSrc
= BitmapDest
;
1091 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1100 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1101 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1102 if ( SourceRect
.left
< 0 )
1104 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1105 SourceRect
.left
= 0;
1107 if ( SourceRect
.top
< 0 )
1109 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1112 if ( SourceRect
.right
< -1 )
1114 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1115 SourceRect
.right
= -1;
1117 if ( SourceRect
.bottom
< -1 )
1119 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1120 SourceRect
.bottom
= -1;
1122 if ( SourceRect
.right
> sw
)
1124 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1125 SourceRect
.right
= sw
;
1127 if ( SourceRect
.bottom
> sh
)
1129 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1130 SourceRect
.bottom
= sh
;
1134 if ( SourceRect
.left
> sw
)
1136 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1137 SourceRect
.left
= 0;
1139 if ( SourceRect
.top
> sh
)
1141 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1144 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1146 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1154 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1155 if (NULL
== BrushObj
)
1157 if (UsesSource
&& hDCSrc
!= hDCDest
)
1159 DC_UnlockDc(hDCSrc
);
1161 DC_UnlockDc(hDCDest
);
1162 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1171 /* Create the XLATEOBJ. */
1174 if (DCDest
->w
.hPalette
!= 0)
1175 DestPalette
= DCDest
->w
.hPalette
;
1177 if (DCSrc
->w
.hPalette
!= 0)
1178 SourcePalette
= DCSrc
->w
.hPalette
;
1180 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1181 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1182 if (NULL
== XlateObj
)
1184 if (UsesSource
&& hDCSrc
!= hDCDest
)
1186 DC_UnlockDc(hDCSrc
);
1188 DC_UnlockDc(hDCDest
);
1189 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1194 /* Perform the bitblt operation */
1195 Status
= IntEngStretchBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
,
1196 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1199 EngDeleteXlate(XlateObj
);
1202 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1205 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1207 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
1209 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
1210 if (UsesSource
&& hDCSrc
!= hDCDest
)
1212 DC_UnlockDc(hDCSrc
);
1214 DC_UnlockDc(hDCDest
);
1219 /* Internal Functions */
1222 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1228 return 2 * ((bmWidth
+15) >> 4);
1231 bmWidth
*= 3; /* fall through */
1233 return bmWidth
+ (bmWidth
& 1);
1243 return 2 * ((bmWidth
+3) >> 2);
1252 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1256 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1262 if (hBitmap
== NULL
)
1265 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1269 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1271 if (Bitmap
->SurfObj
.lDelta
>= 0)
1272 bm
.bmHeight
= -bm
.bmHeight
;
1274 res
= NtGdiCreateBitmapIndirect(&bm
);
1279 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1280 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1281 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1285 GDIOBJ_UnlockObj(hBitmap
);
1291 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1295 if(count
< (INT
) sizeof(DIBSECTION
))
1297 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1301 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1303 memcpy(buffer
, bmp
->dib
, count
);
1309 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1311 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1312 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1313 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1314 Bitmap
.bmPlanes
= 1;
1315 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1316 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1317 memcpy(buffer
, &Bitmap
, count
);