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
= ROP3_USES_SOURCE(ROP
);
53 BOOL UsesPattern
= ROP3_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
,
205 &BrushOrigin
, ROP3_TO_ROP4(ROP
));
207 if (UsesSource
&& XlateObj
!= NULL
)
208 EngDeleteXlate(XlateObj
);
210 if(BitmapDest
!= NULL
)
212 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
214 if (UsesSource
&& BitmapSrc
!= BitmapDest
)
216 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
218 if (BrushObj
!= NULL
)
220 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
222 if (UsesSource
&& hDCSrc
!= hDCDest
)
226 DC_UnlockDc(hDCDest
);
247 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
249 HPALETTE SourcePalette
= 0, DestPalette
= 0;
250 PPALGDI PalDestGDI
, PalSourceGDI
;
251 USHORT PalDestMode
, PalSrcMode
;
252 ULONG TransparentColor
= 0;
255 if(!(DCDest
= DC_LockDc(hdcDst
)))
257 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
258 SetLastWin32Error(ERROR_INVALID_HANDLE
);
262 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
265 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
266 SetLastWin32Error(ERROR_INVALID_HANDLE
);
274 /* Offset positions */
275 xDst
+= DCDest
->w
.DCOrgX
;
276 yDst
+= DCDest
->w
.DCOrgY
;
277 xSrc
+= DCSrc
->w
.DCOrgX
;
278 ySrc
+= DCSrc
->w
.DCOrgY
;
280 if(DCDest
->w
.hPalette
)
281 DestPalette
= DCDest
->w
.hPalette
;
283 if(DCSrc
->w
.hPalette
)
284 SourcePalette
= DCSrc
->w
.hPalette
;
286 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
290 SetLastWin32Error(ERROR_INVALID_HANDLE
);
293 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
295 PALETTE_UnlockPalette(SourcePalette
);
298 SetLastWin32Error(ERROR_INVALID_HANDLE
);
301 if(DestPalette
!= SourcePalette
)
303 PalDestMode
= PalDestGDI
->Mode
;
304 PalSrcMode
= PalSourceGDI
->Mode
;
305 PALETTE_UnlockPalette(DestPalette
);
309 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
311 PALETTE_UnlockPalette(SourcePalette
);
313 /* Translate Transparent (RGB) Color to the source palette */
314 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
316 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
317 EngDeleteXlate(XlateObj
);
320 /* Create the XLATE object to convert colors between source and destination */
321 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
323 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
324 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
326 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
327 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
332 rcDest
.right
= rcDest
.left
+ cxDst
;
333 rcDest
.bottom
= rcDest
.top
+ cyDst
;
336 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
337 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
339 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
341 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
345 Ret
= IntEngTransparentBlt(BitmapDest
, BitmapSrc
, DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
346 TransparentColor
, 0);
349 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
350 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
358 EngDeleteXlate(XlateObj
);
375 /* NOTE: Windows also doesn't store nr. of planes separately! */
376 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
378 /* Check parameters */
379 if (!Height
|| !Width
)
381 Size
.cx
= Size
.cy
= 1;
385 Size
.cx
= abs(Width
);
386 Size
.cy
= abs(Height
);
389 /* Create the bitmap object. */
390 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
391 BitmapFormat(BitsPerPel
, BI_RGB
),
392 (Height
< 0 ? BMF_TOPDOWN
: 0) |
393 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
396 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
400 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
401 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
403 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
404 /* FIXME - bmp can be NULL!!!!!! */
405 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
406 BITMAPOBJ_UnlockBitmap( hBitmap
);
409 * NOTE: It's ugly practice, but we are using the object even
410 * after unlocking. Since the handle is currently known only
411 * to us it should be safe.
416 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
423 BITMAP_Cleanup(PVOID ObjectBody
)
425 PBITMAPOBJ pBmp
= (PBITMAPOBJ
)ObjectBody
;
426 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
427 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
429 if (pBmp
->dib
== NULL
)
431 ExFreePool(pBmp
->SurfObj
.pvBits
);
435 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
444 IntCreateCompatibleBitmap(
453 if ((Width
>= 0x10000) || (Height
>= 0x10000))
455 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
459 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
460 if (0 == Width
|| 0 == Height
)
462 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
466 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
473 NtGdiCreateCompatibleBitmap(
483 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
487 SetLastWin32Error(ERROR_INVALID_HANDLE
);
491 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
493 DPRINT ("\t\t%04x\n", Bmp
);
499 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
501 return NtGdiCreateBitmap (BM
->bmWidth
,
509 NtGdiCreateDiscardableBitmap(
514 /* FIXME: this probably should do something else */
515 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
537 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
541 NtGdiGetBitmapDimensionEx(
547 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
553 *Dimension
= bmp
->dimension
;
555 BITMAPOBJ_UnlockBitmap(hBitmap
);
561 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
564 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
565 BOOL bInRect
= FALSE
;
566 BITMAPOBJ
*BitmapObject
;
567 SURFOBJ
*SurfaceObject
;
571 dc
= DC_LockDc (hDC
);
575 SetLastWin32Error(ERROR_INVALID_HANDLE
);
578 XPos
+= dc
->w
.DCOrgX
;
579 YPos
+= dc
->w
.DCOrgY
;
580 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
583 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
584 SurfaceObject
= &BitmapObject
->SurfObj
;
587 if ( dc
->w
.hPalette
!= 0 )
588 Pal
= dc
->w
.hPalette
;
589 /* FIXME: Verify if it shouldn't be PAL_BGR! */
590 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
593 // check if this DC has a DIB behind it...
594 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
596 ASSERT ( SurfaceObject
->lDelta
);
597 Result
= XLATEOBJ_iXlate(XlateObj
,
598 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
600 EngDeleteXlate(XlateObj
);
602 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
607 // if Result is still CLR_INVALID, then the "quick" method above didn't work
608 if ( bInRect
&& Result
== CLR_INVALID
)
610 // FIXME: create a 1x1 32BPP DIB, and blit to it
611 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
614 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
616 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
617 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
618 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
621 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
626 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
627 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
629 // our bitmap is no longer selected, so we can access it's stuff...
630 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
633 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
634 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
637 NtGdiDeleteObject ( hBmpTmp
);
639 NtGdiDeleteDC ( hDCTmp
);
646 /***********************************************************************
648 * Ported from WINE by sedwards 11-4-03
650 * Someone thought it would be faster to do it here and then switch back
651 * to GDI32. I dunno. Write a test and let me know.
655 SwapROP3_SrcDst(BYTE bRop3
)
657 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
660 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
661 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
662 #define DSTCOPY 0x00AA0029
663 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
667 HDC hdcDest
, INT nXDest
, INT nYDest
,
668 INT nWidth
, INT nHeight
, HDC hdcSrc
,
669 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
670 INT xMask
, INT yMask
, DWORD dwRop
)
672 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
673 HDC hDCMask
, hDC1
, hDC2
;
674 static const DWORD ROP3Table
[256] =
676 0x00000042, 0x00010289,
677 0x00020C89, 0x000300AA,
678 0x00040C88, 0x000500A9,
679 0x00060865, 0x000702C5,
680 0x00080F08, 0x00090245,
681 0x000A0329, 0x000B0B2A,
682 0x000C0324, 0x000D0B25,
683 0x000E08A5, 0x000F0001,
684 0x00100C85, 0x001100A6,
685 0x00120868, 0x001302C8,
686 0x00140869, 0x001502C9,
687 0x00165CCA, 0x00171D54,
688 0x00180D59, 0x00191CC8,
689 0x001A06C5, 0x001B0768,
690 0x001C06CA, 0x001D0766,
691 0x001E01A5, 0x001F0385,
692 0x00200F09, 0x00210248,
693 0x00220326, 0x00230B24,
694 0x00240D55, 0x00251CC5,
695 0x002606C8, 0x00271868,
696 0x00280369, 0x002916CA,
697 0x002A0CC9, 0x002B1D58,
698 0x002C0784, 0x002D060A,
699 0x002E064A, 0x002F0E2A,
700 0x0030032A, 0x00310B28,
701 0x00320688, 0x00330008,
702 0x003406C4, 0x00351864,
703 0x003601A8, 0x00370388,
704 0x0038078A, 0x00390604,
705 0x003A0644, 0x003B0E24,
706 0x003C004A, 0x003D18A4,
707 0x003E1B24, 0x003F00EA,
708 0x00400F0A, 0x00410249,
709 0x00420D5D, 0x00431CC4,
710 0x00440328, 0x00450B29,
711 0x004606C6, 0x0047076A,
712 0x00480368, 0x004916C5,
713 0x004A0789, 0x004B0605,
714 0x004C0CC8, 0x004D1954,
715 0x004E0645, 0x004F0E25,
716 0x00500325, 0x00510B26,
717 0x005206C9, 0x00530764,
718 0x005408A9, 0x00550009,
719 0x005601A9, 0x00570389,
720 0x00580785, 0x00590609,
721 0x005A0049, 0x005B18A9,
722 0x005C0649, 0x005D0E29,
723 0x005E1B29, 0x005F00E9,
724 0x00600365, 0x006116C6,
725 0x00620786, 0x00630608,
726 0x00640788, 0x00650606,
727 0x00660046, 0x006718A8,
728 0x006858A6, 0x00690145,
729 0x006A01E9, 0x006B178A,
730 0x006C01E8, 0x006D1785,
731 0x006E1E28, 0x006F0C65,
732 0x00700CC5, 0x00711D5C,
733 0x00720648, 0x00730E28,
734 0x00740646, 0x00750E26,
735 0x00761B28, 0x007700E6,
736 0x007801E5, 0x00791786,
737 0x007A1E29, 0x007B0C68,
738 0x007C1E24, 0x007D0C69,
739 0x007E0955, 0x007F03C9,
740 0x008003E9, 0x00810975,
741 0x00820C49, 0x00831E04,
742 0x00840C48, 0x00851E05,
743 0x008617A6, 0x008701C5,
744 0x008800C6, 0x00891B08,
745 0x008A0E06, 0x008B0666,
746 0x008C0E08, 0x008D0668,
747 0x008E1D7C, 0x008F0CE5,
748 0x00900C45, 0x00911E08,
749 0x009217A9, 0x009301C4,
750 0x009417AA, 0x009501C9,
751 0x00960169, 0x0097588A,
752 0x00981888, 0x00990066,
753 0x009A0709, 0x009B07A8,
754 0x009C0704, 0x009D07A6,
755 0x009E16E6, 0x009F0345,
756 0x00A000C9, 0x00A11B05,
757 0x00A20E09, 0x00A30669,
758 0x00A41885, 0x00A50065,
759 0x00A60706, 0x00A707A5,
760 0x00A803A9, 0x00A90189,
761 0x00AA0029, 0x00AB0889,
762 0x00AC0744, 0x00AD06E9,
763 0x00AE0B06, 0x00AF0229,
764 0x00B00E05, 0x00B10665,
765 0x00B21974, 0x00B30CE8,
766 0x00B4070A, 0x00B507A9,
767 0x00B616E9, 0x00B70348,
768 0x00B8074A, 0x00B906E6,
769 0x00BA0B09, 0x00BB0226,
770 0x00BC1CE4, 0x00BD0D7D,
771 0x00BE0269, 0x00BF08C9,
772 0x00C000CA, 0x00C11B04,
773 0x00C21884, 0x00C3006A,
774 0x00C40E04, 0x00C50664,
775 0x00C60708, 0x00C707AA,
776 0x00C803A8, 0x00C90184,
777 0x00CA0749, 0x00CB06E4,
778 0x00CC0020, 0x00CD0888,
779 0x00CE0B08, 0x00CF0224,
780 0x00D00E0A, 0x00D1066A,
781 0x00D20705, 0x00D307A4,
782 0x00D41D78, 0x00D50CE9,
783 0x00D616EA, 0x00D70349,
784 0x00D80745, 0x00D906E8,
785 0x00DA1CE9, 0x00DB0D75,
786 0x00DC0B04, 0x00DD0228,
787 0x00DE0268, 0x00DF08C8,
788 0x00E003A5, 0x00E10185,
789 0x00E20746, 0x00E306EA,
790 0x00E40748, 0x00E506E5,
791 0x00E61CE8, 0x00E70D79,
792 0x00E81D74, 0x00E95CE6,
793 0x00EA02E9, 0x00EB0849,
794 0x00EC02E8, 0x00ED0848,
795 0x00EE0086, 0x00EF0A08,
796 0x00F00021, 0x00F10885,
797 0x00F20B05, 0x00F3022A,
798 0x00F40B0A, 0x00F50225,
799 0x00F60265, 0x00F708C5,
800 0x00F802E5, 0x00F90845,
801 0x00FA0089, 0x00FB0A09,
802 0x00FC008A, 0x00FD0A0A,
803 0x00FE02A9, 0x00FF0062,
807 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
809 /* 1. make mask bitmap's dc */
810 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
811 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
813 /* 2. make masked Background bitmap */
815 /* 2.1 make bitmap */
816 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
817 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
818 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
820 /* 2.2 draw dest bitmap and mask */
821 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
822 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
823 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
825 /* 3. make masked Foreground bitmap */
827 /* 3.1 make bitmap */
828 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
829 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
830 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
832 /* 3.2 draw src bitmap and mask */
833 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
834 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
835 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
837 /* 4. combine two bitmap and copy it to hdcDest */
838 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
839 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
841 /* 5. restore all object */
842 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
843 NtGdiSelectObject(hDC1
, hOldBitmap2
);
844 NtGdiSelectObject(hDC2
, hOldBitmap3
);
846 /* 6. delete all temp object */
847 NtGdiDeleteObject(hBitmap2
);
848 NtGdiDeleteObject(hBitmap3
);
852 NtGdiDeleteDC(hDCMask
);
883 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
884 if (bmp
== NULL
|| Bits
== NULL
)
891 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
895 /* Only get entire lines */
896 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
897 if (height
> bmp
->SurfObj
.sizlBitmap
.cy
)
899 height
= bmp
->SurfObj
.sizlBitmap
.cy
;
901 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
902 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
906 bmp
->SurfObj
.sizlBitmap
.cx
,
907 bmp
->SurfObj
.sizlBitmap
.cy
,
908 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
912 /* FIXME: call DDI specific function here if available */
915 DPRINT ("Calling device specific BitmapBits\n");
916 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
918 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
922 DPRINT ("BitmapBits == NULL??\n");
929 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
933 BITMAPOBJ_UnlockBitmap(hBitmap
);
939 NtGdiSetBitmapDimensionEx(
947 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
955 *Size
= bmp
->dimension
;
957 bmp
->dimension
.cx
= Width
;
958 bmp
->dimension
.cy
= Height
;
960 BITMAPOBJ_UnlockBitmap (hBitmap
);
972 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
973 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
977 return ((COLORREF
) -1);
987 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
990 if (NewBrush
== NULL
)
992 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
993 if (OldBrush
== NULL
)
995 NtGdiDeleteObject(NewBrush
);
998 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
999 NtGdiSelectObject(hDC
, OldBrush
);
1000 NtGdiDeleteObject(NewBrush
);
1020 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
1024 XLATEOBJ
*XlateObj
= NULL
;
1025 HPALETTE SourcePalette
= 0, DestPalette
= 0;
1026 PGDIBRUSHOBJ BrushObj
;
1027 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1028 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1030 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1032 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1035 DCDest
= DC_LockDc(hDCDest
);
1038 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1039 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1045 if (hDCSrc
!= hDCDest
)
1047 DCSrc
= DC_LockDc(hDCSrc
);
1050 DC_UnlockDc(hDCDest
);
1051 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1052 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1066 /* Offset the destination and source by the origin of their DCs. */
1067 XOriginDest
+= DCDest
->w
.DCOrgX
;
1068 YOriginDest
+= DCDest
->w
.DCOrgY
;
1071 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1072 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1075 DestRect
.left
= XOriginDest
;
1076 DestRect
.top
= YOriginDest
;
1077 DestRect
.right
= XOriginDest
+WidthDest
;
1078 DestRect
.bottom
= YOriginDest
+HeightDest
;
1080 SourceRect
.left
= XOriginSrc
;
1081 SourceRect
.top
= YOriginSrc
;
1082 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1083 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1085 /* Determine surfaces to be used in the bitblt */
1086 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1089 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1090 BitmapSrc
= BitmapDest
;
1092 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1101 int sw
= BitmapSrc
->SurfObj
.sizlBitmap
.cx
;
1102 int sh
= BitmapSrc
->SurfObj
.sizlBitmap
.cy
;
1103 if ( SourceRect
.left
< 0 )
1105 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
)/abs(SourceRect
.right
-SourceRect
.left
);
1106 SourceRect
.left
= 0;
1108 if ( SourceRect
.top
< 0 )
1110 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1113 if ( SourceRect
.right
< -1 )
1115 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * (-1-SourceRect
.left
)/abs(SourceRect
.right
-SourceRect
.left
);
1116 SourceRect
.right
= -1;
1118 if ( SourceRect
.bottom
< -1 )
1120 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * (-1-SourceRect
.top
)/abs(SourceRect
.bottom
-SourceRect
.top
);
1121 SourceRect
.bottom
= -1;
1123 if ( SourceRect
.right
> sw
)
1125 DestRect
.right
= DestRect
.left
+ (DestRect
.right
-DestRect
.left
) * abs(sw
-SourceRect
.left
) / abs(SourceRect
.right
-SourceRect
.left
);
1126 SourceRect
.right
= sw
;
1128 if ( SourceRect
.bottom
> sh
)
1130 DestRect
.bottom
= DestRect
.top
+ (DestRect
.bottom
-DestRect
.top
) * abs(sh
-SourceRect
.top
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1131 SourceRect
.bottom
= sh
;
1135 if ( SourceRect
.left
> sw
)
1137 DestRect
.left
= DestRect
.right
- (DestRect
.right
-DestRect
.left
) * (SourceRect
.right
-sw
) / abs(SourceRect
.right
-SourceRect
.left
);
1138 SourceRect
.left
= 0;
1140 if ( SourceRect
.top
> sh
)
1142 DestRect
.top
= DestRect
.bottom
- (DestRect
.bottom
-DestRect
.top
) * (SourceRect
.bottom
-sh
) / abs(SourceRect
.bottom
-SourceRect
.top
);
1145 if (0 == (DestRect
.right
-DestRect
.left
) || 0 == (DestRect
.bottom
-DestRect
.top
) || 0 == (SourceRect
.right
-SourceRect
.left
) || 0 == (SourceRect
.bottom
-SourceRect
.top
))
1147 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1155 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1156 if (NULL
== BrushObj
)
1158 if (UsesSource
&& hDCSrc
!= hDCDest
)
1160 DC_UnlockDc(hDCSrc
);
1162 DC_UnlockDc(hDCDest
);
1163 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1172 /* Create the XLATEOBJ. */
1175 if (DCDest
->w
.hPalette
!= 0)
1176 DestPalette
= DCDest
->w
.hPalette
;
1178 if (DCSrc
->w
.hPalette
!= 0)
1179 SourcePalette
= DCSrc
->w
.hPalette
;
1181 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1182 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1183 if (NULL
== XlateObj
)
1185 if (UsesSource
&& hDCSrc
!= hDCDest
)
1187 DC_UnlockDc(hDCSrc
);
1189 DC_UnlockDc(hDCDest
);
1190 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1195 /* Perform the bitblt operation */
1196 Status
= IntEngStretchBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
,
1197 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1200 EngDeleteXlate(XlateObj
);
1203 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1206 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1208 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
1210 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
1211 if (UsesSource
&& hDCSrc
!= hDCDest
)
1213 DC_UnlockDc(hDCSrc
);
1215 DC_UnlockDc(hDCDest
);
1220 /* Internal Functions */
1223 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1229 return 2 * ((bmWidth
+15) >> 4);
1232 bmWidth
*= 3; /* fall through */
1234 return bmWidth
+ (bmWidth
& 1);
1244 return 2 * ((bmWidth
+3) >> 2);
1253 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1257 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1263 if (hBitmap
== NULL
)
1266 Bitmap
= GDIOBJ_LockObj(hBitmap
, GDI_OBJECT_TYPE_BITMAP
);
1270 BITMAP_GetObject(Bitmap
, sizeof(BITMAP
), &bm
);
1272 if (Bitmap
->SurfObj
.lDelta
>= 0)
1273 bm
.bmHeight
= -bm
.bmHeight
;
1275 res
= NtGdiCreateBitmapIndirect(&bm
);
1280 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), TAG_BITMAP
);
1281 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1282 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* abs(bm
.bmHeight
), buf
);
1286 GDIOBJ_UnlockObj(hBitmap
);
1292 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1296 if(count
< (INT
) sizeof(DIBSECTION
))
1298 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1302 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1304 memcpy(buffer
, bmp
->dib
, count
);
1310 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1312 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1313 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1314 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1315 Bitmap
.bmPlanes
= 1;
1316 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1317 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1318 memcpy(buffer
, &Bitmap
, count
);