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.81 2004/11/21 10:55:29 navaraf Exp $ */
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 DC_UnlockDc(hDCDest
);
130 SetLastWin32Error(ERROR_INVALID_HANDLE
);
133 BrushOrigin
= BrushObj
->ptOrigin
;
134 IntGdiInitBrushInstance(&BrushInst
, BrushObj
, DCDest
->XlateBrush
);
141 /* Create the XLATEOBJ. */
144 if (DCDest
->w
.hPalette
!= 0)
145 DestPalette
= DCDest
->w
.hPalette
;
147 if (DCSrc
->w
.hPalette
!= 0)
148 SourcePalette
= DCSrc
->w
.hPalette
;
150 /* KB41464 details how to convert between mono and color */
151 if (DCDest
->w
.bitsPerPixel
== DCSrc
->w
.bitsPerPixel
== 1)
157 if (DCDest
->w
.bitsPerPixel
== 1)
159 XlateObj
= IntEngCreateMonoXlate(0, DestPalette
, SourcePalette
, DCSrc
->w
.backgroundColor
);
161 else if (DCSrc
->w
.bitsPerPixel
== 1)
163 XlateObj
= IntEngCreateSrcMonoXlate(DestPalette
, DCSrc
->w
.backgroundColor
, DCSrc
->w
.textColor
);
167 XlateObj
= IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
169 if (NULL
== XlateObj
)
171 if (UsesSource
&& hDCSrc
!= hDCDest
)
175 DC_UnlockDc(hDCDest
);
176 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
182 /* Perform the bitblt operation */
183 Status
= IntEngBitBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
, XlateObj
,
184 &DestRect
, &SourcePoint
, NULL
, BrushObj
? &BrushInst
.BrushObject
: NULL
, &BrushOrigin
, ROP
);
186 if (UsesSource
&& XlateObj
!= NULL
)
187 EngDeleteXlate(XlateObj
);
188 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
189 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
191 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
195 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
197 if (UsesSource
&& hDCSrc
!= hDCDest
)
201 DC_UnlockDc(hDCDest
);
222 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
224 HPALETTE SourcePalette
= 0, DestPalette
= 0;
225 PPALGDI PalDestGDI
, PalSourceGDI
;
226 USHORT PalDestMode
, PalSrcMode
;
227 ULONG TransparentColor
= 0;
230 if(!(DCDest
= DC_LockDc(hdcDst
)))
232 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst
);
233 SetLastWin32Error(ERROR_INVALID_HANDLE
);
237 if((hdcDst
!= hdcSrc
) && !(DCSrc
= DC_LockDc(hdcSrc
)))
240 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc
);
241 SetLastWin32Error(ERROR_INVALID_HANDLE
);
249 /* Offset positions */
250 xDst
+= DCDest
->w
.DCOrgX
;
251 yDst
+= DCDest
->w
.DCOrgY
;
252 xSrc
+= DCSrc
->w
.DCOrgX
;
253 ySrc
+= DCSrc
->w
.DCOrgY
;
255 if(DCDest
->w
.hPalette
)
256 DestPalette
= DCDest
->w
.hPalette
;
258 if(DCSrc
->w
.hPalette
)
259 SourcePalette
= DCSrc
->w
.hPalette
;
261 if(!(PalSourceGDI
= PALETTE_LockPalette(SourcePalette
)))
265 SetLastWin32Error(ERROR_INVALID_HANDLE
);
268 if((DestPalette
!= SourcePalette
) && !(PalDestGDI
= PALETTE_LockPalette(DestPalette
)))
270 PALETTE_UnlockPalette(SourcePalette
);
273 SetLastWin32Error(ERROR_INVALID_HANDLE
);
276 if(DestPalette
!= SourcePalette
)
278 PalDestMode
= PalDestGDI
->Mode
;
279 PalSrcMode
= PalSourceGDI
->Mode
;
280 PALETTE_UnlockPalette(DestPalette
);
284 PalDestMode
= PalSrcMode
= PalSourceGDI
->Mode
;
286 PALETTE_UnlockPalette(SourcePalette
);
288 /* Translate Transparent (RGB) Color to the source palette */
289 if((XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalSrcMode
, PAL_RGB
, SourcePalette
, NULL
)))
291 TransparentColor
= XLATEOBJ_iXlate(XlateObj
, (ULONG
)TransColor
);
292 EngDeleteXlate(XlateObj
);
295 /* Create the XLATE object to convert colors between source and destination */
296 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(PalDestMode
, PalSrcMode
, DestPalette
, SourcePalette
);
298 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
300 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
305 rcDest
.right
= rcDest
.left
+ cxDst
;
306 rcDest
.bottom
= rcDest
.top
+ cyDst
;
309 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
310 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
312 if((cxDst
!= cxSrc
) || (cyDst
!= cySrc
))
314 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
318 Ret
= IntEngTransparentBlt(BitmapDest
, BitmapSrc
, DCDest
->CombinedClip
, XlateObj
, &rcDest
, &rcSrc
,
319 TransparentColor
, 0);
322 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
323 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
331 EngDeleteXlate(XlateObj
);
348 /* NOTE: Windows also doesn't store nr. of planes separately! */
349 BitsPerPel
= (BYTE
)BitsPerPel
* (BYTE
)Planes
;
351 /* Check parameters */
352 if (!Height
|| !Width
)
354 Size
.cx
= Size
.cy
= 1;
358 Size
.cx
= abs(Width
);
359 Size
.cy
= abs(Height
);
362 /* Create the bitmap object. */
363 hBitmap
= IntCreateBitmap(Size
, BITMAPOBJ_GetWidthBytes(Width
, BitsPerPel
),
364 BitmapFormat(BitsPerPel
, BI_RGB
),
365 (Height
> 0 ? 0 : BMF_TOPDOWN
) |
366 (Bits
== NULL
? 0 : BMF_NOZEROINIT
), NULL
);
369 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
373 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
374 Size
.cx
, Size
.cy
, BitsPerPel
, hBitmap
);
376 bmp
= BITMAPOBJ_LockBitmap( hBitmap
);
377 bmp
->flFlags
= BITMAPOBJ_IS_APIBITMAP
;
378 BITMAPOBJ_UnlockBitmap( hBitmap
);
381 * NOTE: It's ugly practice, but we are using the object even
382 * after unlocking. Since the handle is currently known only
383 * to us it should be safe.
388 NtGdiSetBitmapBits(hBitmap
, bmp
->SurfObj
.cjBits
, Bits
);
395 Bitmap_InternalDelete( PBITMAPOBJ pBmp
)
399 if (pBmp
->SurfObj
.pvBits
!= NULL
&&
400 (pBmp
->flFlags
& BITMAPOBJ_IS_APIBITMAP
))
402 if (pBmp
->dib
== NULL
)
404 ExFreePool(pBmp
->SurfObj
.pvBits
);
408 EngFreeUserMem(pBmp
->SurfObj
.pvBits
);
417 IntCreateCompatibleBitmap(
426 if ((Width
>= 0x10000) || (Height
>= 0x10000))
428 DPRINT1("got bad width %d or height %d, please look for reason\n", Width
, Height
);
432 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
433 if (0 == Width
|| 0 == Height
)
435 Bmp
= NtGdiCreateBitmap (1, 1, 1, 1, NULL
);
439 Bmp
= NtGdiCreateBitmap(Width
, Height
, 1, Dc
->w
.bitsPerPixel
, NULL
);
446 NtGdiCreateCompatibleBitmap(
456 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC
, Width
, Height
, Dc
->w
.bitsPerPixel
);
460 SetLastWin32Error(ERROR_INVALID_HANDLE
);
464 Bmp
= IntCreateCompatibleBitmap(Dc
, Width
, Height
);
466 DPRINT ("\t\t%04x\n", Bmp
);
472 NtGdiCreateBitmapIndirect(CONST BITMAP
*BM
)
474 return NtGdiCreateBitmap (BM
->bmWidth
,
482 NtGdiCreateDiscardableBitmap(
487 /* FIXME: this probably should do something else */
488 return NtGdiCreateCompatibleBitmap(hDC
, Width
, Height
);
510 return NtGdiExtFloodFill(hDC
, XStart
, YStart
, Fill
, FLOODFILLBORDER
);
514 NtGdiGetBitmapDimensionEx(
520 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
526 *Dimension
= bmp
->dimension
;
528 BITMAPOBJ_UnlockBitmap(hBitmap
);
534 NtGdiGetPixel(HDC hDC
, INT XPos
, INT YPos
)
537 COLORREF Result
= (COLORREF
)CLR_INVALID
; // default to failure
538 BOOL bInRect
= FALSE
;
539 BITMAPOBJ
*BitmapObject
;
540 SURFOBJ
*SurfaceObject
;
544 dc
= DC_LockDc (hDC
);
548 SetLastWin32Error(ERROR_INVALID_HANDLE
);
551 XPos
+= dc
->w
.DCOrgX
;
552 YPos
+= dc
->w
.DCOrgY
;
553 if ( IN_RECT(dc
->CombinedClip
->rclBounds
,XPos
,YPos
) )
556 BitmapObject
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
557 SurfaceObject
= &BitmapObject
->SurfObj
;
560 if ( dc
->w
.hPalette
!= 0 )
561 Pal
= dc
->w
.hPalette
;
562 /* FIXME: Verify if it shouldn't be PAL_BGR! */
563 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate ( PAL_RGB
, 0, NULL
, Pal
);
566 // check if this DC has a DIB behind it...
567 if ( SurfaceObject
->pvScan0
) // STYPE_BITMAP == SurfaceObject->iType
569 ASSERT ( SurfaceObject
->lDelta
);
570 Result
= XLATEOBJ_iXlate(XlateObj
,
571 DibFunctionsForBitmapFormat
[SurfaceObject
->iBitmapFormat
].DIB_GetPixel ( SurfaceObject
, XPos
, YPos
) );
573 EngDeleteXlate(XlateObj
);
576 BITMAPOBJ_UnlockBitmap(dc
->w
.hBitmap
);
580 // if Result is still CLR_INVALID, then the "quick" method above didn't work
581 if ( bInRect
&& Result
== CLR_INVALID
)
583 // FIXME: create a 1x1 32BPP DIB, and blit to it
584 HDC hDCTmp
= NtGdiCreateCompatableDC(hDC
);
587 static const BITMAPINFOHEADER bih
= { sizeof(BITMAPINFOHEADER
), 1, 1, 1, 32, BI_RGB
, 0, 0, 0, 0, 0 };
589 RtlMoveMemory ( &(bi
.bmiHeader
), &bih
, sizeof(bih
) );
590 HBITMAP hBmpTmp
= NtGdiCreateDIBitmap ( hDC
, &bi
.bmiHeader
, 0, NULL
, &bi
, DIB_RGB_COLORS
);
591 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
594 HBITMAP hBmpOld
= (HBITMAP
)NtGdiSelectObject ( hDCTmp
, hBmpTmp
);
599 NtGdiBitBlt ( hDCTmp
, 0, 0, 1, 1, hDC
, XPos
, YPos
, SRCCOPY
);
600 NtGdiSelectObject ( hDCTmp
, hBmpOld
);
602 // our bitmap is no longer selected, so we can access it's stuff...
603 bmpobj
= BITMAPOBJ_LockBitmap ( hBmpTmp
);
606 Result
= *(COLORREF
*)bmpobj
->SurfObj
.pvScan0
;
607 BITMAPOBJ_UnlockBitmap ( hBmpTmp
);
610 NtGdiDeleteObject ( hBmpTmp
);
612 NtGdiDeleteDC ( hDCTmp
);
619 /***********************************************************************
621 * Ported from WINE by sedwards 11-4-03
623 * Someone thought it would be faster to do it here and then switch back
624 * to GDI32. I dunno. Write a test and let me know.
628 SwapROP3_SrcDst(BYTE bRop3
)
630 return (bRop3
& 0x99) | ((bRop3
& 0x22) << 1) | ((bRop3
& 0x44) >> 1);
633 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
634 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
635 #define DSTCOPY 0x00AA0029
636 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
640 HDC hdcDest
, INT nXDest
, INT nYDest
,
641 INT nWidth
, INT nHeight
, HDC hdcSrc
,
642 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
643 INT xMask
, INT yMask
, DWORD dwRop
)
645 HBITMAP hOldMaskBitmap
, hBitmap2
, hOldBitmap2
, hBitmap3
, hOldBitmap3
;
646 HDC hDCMask
, hDC1
, hDC2
;
647 static const DWORD ROP3Table
[256] =
649 0x00000042, 0x00010289,
650 0x00020C89, 0x000300AA,
651 0x00040C88, 0x000500A9,
652 0x00060865, 0x000702C5,
653 0x00080F08, 0x00090245,
654 0x000A0329, 0x000B0B2A,
655 0x000C0324, 0x000D0B25,
656 0x000E08A5, 0x000F0001,
657 0x00100C85, 0x001100A6,
658 0x00120868, 0x001302C8,
659 0x00140869, 0x001502C9,
660 0x00165CCA, 0x00171D54,
661 0x00180D59, 0x00191CC8,
662 0x001A06C5, 0x001B0768,
663 0x001C06CA, 0x001D0766,
664 0x001E01A5, 0x001F0385,
665 0x00200F09, 0x00210248,
666 0x00220326, 0x00230B24,
667 0x00240D55, 0x00251CC5,
668 0x002606C8, 0x00271868,
669 0x00280369, 0x002916CA,
670 0x002A0CC9, 0x002B1D58,
671 0x002C0784, 0x002D060A,
672 0x002E064A, 0x002F0E2A,
673 0x0030032A, 0x00310B28,
674 0x00320688, 0x00330008,
675 0x003406C4, 0x00351864,
676 0x003601A8, 0x00370388,
677 0x0038078A, 0x00390604,
678 0x003A0644, 0x003B0E24,
679 0x003C004A, 0x003D18A4,
680 0x003E1B24, 0x003F00EA,
681 0x00400F0A, 0x00410249,
682 0x00420D5D, 0x00431CC4,
683 0x00440328, 0x00450B29,
684 0x004606C6, 0x0047076A,
685 0x00480368, 0x004916C5,
686 0x004A0789, 0x004B0605,
687 0x004C0CC8, 0x004D1954,
688 0x004E0645, 0x004F0E25,
689 0x00500325, 0x00510B26,
690 0x005206C9, 0x00530764,
691 0x005408A9, 0x00550009,
692 0x005601A9, 0x00570389,
693 0x00580785, 0x00590609,
694 0x005A0049, 0x005B18A9,
695 0x005C0649, 0x005D0E29,
696 0x005E1B29, 0x005F00E9,
697 0x00600365, 0x006116C6,
698 0x00620786, 0x00630608,
699 0x00640788, 0x00650606,
700 0x00660046, 0x006718A8,
701 0x006858A6, 0x00690145,
702 0x006A01E9, 0x006B178A,
703 0x006C01E8, 0x006D1785,
704 0x006E1E28, 0x006F0C65,
705 0x00700CC5, 0x00711D5C,
706 0x00720648, 0x00730E28,
707 0x00740646, 0x00750E26,
708 0x00761B28, 0x007700E6,
709 0x007801E5, 0x00791786,
710 0x007A1E29, 0x007B0C68,
711 0x007C1E24, 0x007D0C69,
712 0x007E0955, 0x007F03C9,
713 0x008003E9, 0x00810975,
714 0x00820C49, 0x00831E04,
715 0x00840C48, 0x00851E05,
716 0x008617A6, 0x008701C5,
717 0x008800C6, 0x00891B08,
718 0x008A0E06, 0x008B0666,
719 0x008C0E08, 0x008D0668,
720 0x008E1D7C, 0x008F0CE5,
721 0x00900C45, 0x00911E08,
722 0x009217A9, 0x009301C4,
723 0x009417AA, 0x009501C9,
724 0x00960169, 0x0097588A,
725 0x00981888, 0x00990066,
726 0x009A0709, 0x009B07A8,
727 0x009C0704, 0x009D07A6,
728 0x009E16E6, 0x009F0345,
729 0x00A000C9, 0x00A11B05,
730 0x00A20E09, 0x00A30669,
731 0x00A41885, 0x00A50065,
732 0x00A60706, 0x00A707A5,
733 0x00A803A9, 0x00A90189,
734 0x00AA0029, 0x00AB0889,
735 0x00AC0744, 0x00AD06E9,
736 0x00AE0B06, 0x00AF0229,
737 0x00B00E05, 0x00B10665,
738 0x00B21974, 0x00B30CE8,
739 0x00B4070A, 0x00B507A9,
740 0x00B616E9, 0x00B70348,
741 0x00B8074A, 0x00B906E6,
742 0x00BA0B09, 0x00BB0226,
743 0x00BC1CE4, 0x00BD0D7D,
744 0x00BE0269, 0x00BF08C9,
745 0x00C000CA, 0x00C11B04,
746 0x00C21884, 0x00C3006A,
747 0x00C40E04, 0x00C50664,
748 0x00C60708, 0x00C707AA,
749 0x00C803A8, 0x00C90184,
750 0x00CA0749, 0x00CB06E4,
751 0x00CC0020, 0x00CD0888,
752 0x00CE0B08, 0x00CF0224,
753 0x00D00E0A, 0x00D1066A,
754 0x00D20705, 0x00D307A4,
755 0x00D41D78, 0x00D50CE9,
756 0x00D616EA, 0x00D70349,
757 0x00D80745, 0x00D906E8,
758 0x00DA1CE9, 0x00DB0D75,
759 0x00DC0B04, 0x00DD0228,
760 0x00DE0268, 0x00DF08C8,
761 0x00E003A5, 0x00E10185,
762 0x00E20746, 0x00E306EA,
763 0x00E40748, 0x00E506E5,
764 0x00E61CE8, 0x00E70D79,
765 0x00E81D74, 0x00E95CE6,
766 0x00EA02E9, 0x00EB0849,
767 0x00EC02E8, 0x00ED0848,
768 0x00EE0086, 0x00EF0A08,
769 0x00F00021, 0x00F10885,
770 0x00F20B05, 0x00F3022A,
771 0x00F40B0A, 0x00F50225,
772 0x00F60265, 0x00F708C5,
773 0x00F802E5, 0x00F90845,
774 0x00FA0089, 0x00FB0A09,
775 0x00FC008A, 0x00FD0A0A,
776 0x00FE02A9, 0x00FF0062,
780 return NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
782 /* 1. make mask bitmap's dc */
783 hDCMask
= NtGdiCreateCompatableDC(hdcDest
);
784 hOldMaskBitmap
= (HBITMAP
)NtGdiSelectObject(hDCMask
, hbmMask
);
786 /* 2. make masked Background bitmap */
788 /* 2.1 make bitmap */
789 hDC1
= NtGdiCreateCompatableDC(hdcDest
);
790 hBitmap2
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
791 hOldBitmap2
= (HBITMAP
)NtGdiSelectObject(hDC1
, hBitmap2
);
793 /* 2.2 draw dest bitmap and mask */
794 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
795 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, BKGND_ROP3(dwRop
));
796 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, DSTERASE
);
798 /* 3. make masked Foreground bitmap */
800 /* 3.1 make bitmap */
801 hDC2
= NtGdiCreateCompatableDC(hdcDest
);
802 hBitmap3
= NtGdiCreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
803 hOldBitmap3
= (HBITMAP
)NtGdiSelectObject(hDC2
, hBitmap3
);
805 /* 3.2 draw src bitmap and mask */
806 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
807 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
808 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDCMask
, xMask
, yMask
, SRCAND
);
810 /* 4. combine two bitmap and copy it to hdcDest */
811 NtGdiBitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hDC2
, 0, 0, SRCPAINT
);
812 NtGdiBitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC1
, 0, 0, SRCCOPY
);
814 /* 5. restore all object */
815 NtGdiSelectObject(hDCMask
, hOldMaskBitmap
);
816 NtGdiSelectObject(hDC1
, hOldBitmap2
);
817 NtGdiSelectObject(hDC2
, hOldBitmap3
);
819 /* 6. delete all temp object */
820 NtGdiDeleteObject(hBitmap2
);
821 NtGdiDeleteObject(hBitmap3
);
825 NtGdiDeleteDC(hDCMask
);
856 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
857 if (bmp
== NULL
|| Bits
== NULL
)
864 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes
);
868 /* Only get entire lines */
869 height
= Bytes
/ abs(bmp
->SurfObj
.lDelta
);
870 if (height
> bmp
->SurfObj
.sizlBitmap
.cx
)
872 height
= bmp
->SurfObj
.sizlBitmap
.cx
;
874 Bytes
= height
* abs(bmp
->SurfObj
.lDelta
);
875 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
879 bmp
->SurfObj
.sizlBitmap
.cx
,
880 bmp
->SurfObj
.sizlBitmap
.cy
,
881 1 << BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
),
885 /* FIXME: call DDI specific function here if available */
888 DPRINT ("Calling device specific BitmapBits\n");
889 if (bmp
->DDBitmap
->funcs
->pBitmapBits
)
891 ret
= bmp
->DDBitmap
->funcs
->pBitmapBits(hBitmap
, (void *) Bits
, Bytes
, DDB_SET
);
895 DPRINT ("BitmapBits == NULL??\n");
902 memcpy(bmp
->SurfObj
.pvBits
, Bits
, Bytes
);
906 BITMAPOBJ_UnlockBitmap(hBitmap
);
912 NtGdiSetBitmapDimensionEx(
920 bmp
= BITMAPOBJ_LockBitmap(hBitmap
);
928 *Size
= bmp
->dimension
;
930 bmp
->dimension
.cx
= Width
;
931 bmp
->dimension
.cy
= Height
;
933 BITMAPOBJ_UnlockBitmap (hBitmap
);
945 COLORREF cr
= NtGdiGetPixel(hDC
,X
,Y
);
946 if(cr
!= CLR_INVALID
&& NtGdiSetPixelV(hDC
,X
,Y
,Color
))
950 return ((COLORREF
) -1);
960 HBRUSH NewBrush
= NtGdiCreateSolidBrush(Color
);
963 if (NewBrush
== NULL
)
965 OldBrush
= NtGdiSelectObject(hDC
, NewBrush
);
966 if (OldBrush
== NULL
)
968 NtGdiDeleteObject(NewBrush
);
971 NtGdiPatBlt(hDC
, X
, Y
, 1, 1, PATCOPY
);
972 NtGdiSelectObject(hDC
, OldBrush
);
973 NtGdiDeleteObject(NewBrush
);
993 BITMAPOBJ
*BitmapDest
, *BitmapSrc
;
997 XLATEOBJ
*XlateObj
= NULL
;
998 HPALETTE SourcePalette
= 0, DestPalette
= 0;
999 PGDIBRUSHOBJ BrushObj
;
1000 BOOL UsesSource
= ((ROP
& 0xCC0000) >> 2) != (ROP
& 0x330000);
1001 BOOL UsesPattern
= ((ROP
& 0xF00000) >> 4) != (ROP
& 0x0F0000);
1003 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
1005 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1008 DCDest
= DC_LockDc(hDCDest
);
1011 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest
);
1012 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1018 if (hDCSrc
!= hDCDest
)
1020 DCSrc
= DC_LockDc(hDCSrc
);
1023 DC_UnlockDc(hDCDest
);
1024 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc
);
1025 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1039 /* Offset the destination and source by the origin of their DCs. */
1040 XOriginDest
+= DCDest
->w
.DCOrgX
;
1041 YOriginDest
+= DCDest
->w
.DCOrgY
;
1044 XOriginSrc
+= DCSrc
->w
.DCOrgX
;
1045 YOriginSrc
+= DCSrc
->w
.DCOrgY
;
1048 DestRect
.left
= XOriginDest
;
1049 DestRect
.top
= YOriginDest
;
1050 DestRect
.right
= XOriginDest
+WidthDest
;
1051 DestRect
.bottom
= YOriginDest
+HeightDest
;
1053 SourceRect
.left
= XOriginSrc
;
1054 SourceRect
.top
= YOriginSrc
;
1055 SourceRect
.right
= XOriginSrc
+WidthSrc
;
1056 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
1058 /* Determine surfaces to be used in the bitblt */
1059 BitmapDest
= BITMAPOBJ_LockBitmap(DCDest
->w
.hBitmap
);
1062 if (DCSrc
->w
.hBitmap
== DCDest
->w
.hBitmap
)
1063 BitmapSrc
= BitmapDest
;
1065 BitmapSrc
= BITMAPOBJ_LockBitmap(DCSrc
->w
.hBitmap
);
1074 BrushObj
= BRUSHOBJ_LockBrush(DCDest
->w
.hBrush
);
1075 if (NULL
== BrushObj
)
1077 if (UsesSource
&& hDCSrc
!= hDCDest
)
1079 DC_UnlockDc(hDCSrc
);
1081 DC_UnlockDc(hDCDest
);
1082 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1091 /* Create the XLATEOBJ. */
1094 if (DCDest
->w
.hPalette
!= 0)
1095 DestPalette
= DCDest
->w
.hPalette
;
1097 if (DCSrc
->w
.hPalette
!= 0)
1098 SourcePalette
= DCSrc
->w
.hPalette
;
1100 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1101 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(0, 0, DestPalette
, SourcePalette
);
1102 if (NULL
== XlateObj
)
1104 if (UsesSource
&& hDCSrc
!= hDCDest
)
1106 DC_UnlockDc(hDCSrc
);
1108 DC_UnlockDc(hDCDest
);
1109 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1114 /* Perform the bitblt operation */
1115 Status
= IntEngStretchBlt(BitmapDest
, BitmapSrc
, NULL
, DCDest
->CombinedClip
,
1116 XlateObj
, &DestRect
, &SourceRect
, NULL
, NULL
, NULL
, COLORONCOLOR
);
1119 EngDeleteXlate(XlateObj
);
1120 BITMAPOBJ_UnlockBitmap(DCDest
->w
.hBitmap
);
1121 if (UsesSource
&& DCSrc
->w
.hBitmap
!= DCDest
->w
.hBitmap
)
1123 BITMAPOBJ_UnlockBitmap(DCSrc
->w
.hBitmap
);
1127 BRUSHOBJ_UnlockBrush(DCDest
->w
.hBrush
);
1129 if (UsesSource
&& hDCSrc
!= hDCDest
)
1131 DC_UnlockDc(hDCSrc
);
1133 DC_UnlockDc(hDCDest
);
1138 /* Internal Functions */
1141 BITMAPOBJ_GetWidthBytes (INT bmWidth
, INT bpp
)
1147 return 2 * ((bmWidth
+15) >> 4);
1150 bmWidth
*= 3; /* fall through */
1152 return bmWidth
+ (bmWidth
& 1);
1162 return 2 * ((bmWidth
+3) >> 2);
1171 return ((bmWidth
* bpp
+ 15) & ~15) >> 3;
1175 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap
)
1180 if (IntGdiGetObject(hBitmap
, sizeof(BITMAP
), &bm
) == 0)
1185 res
= NtGdiCreateBitmapIndirect(&bm
);
1190 buf
= ExAllocatePoolWithTag (PagedPool
, bm
.bmWidthBytes
* bm
.bmHeight
, TAG_BITMAP
);
1191 NtGdiGetBitmapBits (hBitmap
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1192 NtGdiSetBitmapBits (res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
1200 BITMAP_GetObject(BITMAPOBJ
* bmp
, INT count
, LPVOID buffer
)
1204 if(count
< (INT
) sizeof(DIBSECTION
))
1206 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1210 if (count
> (INT
) sizeof(DIBSECTION
)) count
= sizeof(DIBSECTION
);
1212 memcpy(buffer
, bmp
->dib
, count
);
1218 if (count
> (INT
) sizeof(BITMAP
)) count
= sizeof(BITMAP
);
1220 Bitmap
.bmWidth
= bmp
->SurfObj
.sizlBitmap
.cx
;
1221 Bitmap
.bmHeight
= bmp
->SurfObj
.sizlBitmap
.cy
;
1222 Bitmap
.bmWidthBytes
= abs(bmp
->SurfObj
.lDelta
);
1223 Bitmap
.bmPlanes
= 1;
1224 Bitmap
.bmBitsPixel
= BitsPerFormat(bmp
->SurfObj
.iBitmapFormat
);
1225 Bitmap
.bmBits
= bmp
->SurfObj
.pvBits
;
1226 memcpy(buffer
, &Bitmap
, count
);