- Move NCI generated files to arch-specific directories
[reactos.git] / reactos / subsystems / win32 / win32k / objects / bitmaps.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id$ */
20
21 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 #define IN_RECT(r,x,y) \
27 ( \
28 (x) >= (r).left && \
29 (y) >= (r).top && \
30 (x) < (r).right && \
31 (y) < (r).bottom \
32 )
33
34 BOOL STDCALL
35 NtGdiBitBlt(
36 HDC hDCDest,
37 INT XDest,
38 INT YDest,
39 INT Width,
40 INT Height,
41 HDC hDCSrc,
42 INT XSrc,
43 INT YSrc,
44 DWORD ROP,
45 IN DWORD crBackColor,
46 IN FLONG fl)
47 {
48 PDC DCDest = NULL;
49 PDC DCSrc = NULL;
50 BITMAPOBJ *BitmapDest, *BitmapSrc;
51 RECTL DestRect;
52 POINTL SourcePoint, BrushOrigin;
53 BOOL Status;
54 XLATEOBJ *XlateObj = NULL;
55 HPALETTE SourcePalette = 0, DestPalette = 0;
56 PGDIBRUSHOBJ BrushObj;
57 GDIBRUSHINST BrushInst;
58 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
59 BOOL UsesPattern = ROP3_USES_PATTERN(ROP);
60
61 DCDest = DC_LockDc(hDCDest);
62 if (NULL == DCDest)
63 {
64 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
65 SetLastWin32Error(ERROR_INVALID_HANDLE);
66 return FALSE;
67 }
68 if (DCDest->IsIC)
69 {
70 DC_UnlockDc(DCDest);
71 /* Yes, Windows really returns TRUE in this case */
72 return TRUE;
73 }
74
75 if (UsesSource)
76 {
77 if (hDCSrc != hDCDest)
78 {
79 DCSrc = DC_LockDc(hDCSrc);
80 if (NULL == DCSrc)
81 {
82 DC_UnlockDc(DCDest);
83 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
84 SetLastWin32Error(ERROR_INVALID_HANDLE);
85 return FALSE;
86 }
87 if (DCSrc->IsIC)
88 {
89 DC_UnlockDc(DCSrc);
90 DC_UnlockDc(DCDest);
91 /* Yes, Windows really returns TRUE in this case */
92 return TRUE;
93 }
94 }
95 else
96 {
97 DCSrc = DCDest;
98 }
99 }
100 else
101 {
102 DCSrc = NULL;
103 }
104
105 /* Offset the destination and source by the origin of their DCs. */
106 XDest += DCDest->w.DCOrgX;
107 YDest += DCDest->w.DCOrgY;
108 if (UsesSource)
109 {
110 XSrc += DCSrc->w.DCOrgX;
111 YSrc += DCSrc->w.DCOrgY;
112 }
113
114 DestRect.left = XDest;
115 DestRect.top = YDest;
116 DestRect.right = XDest+Width;
117 DestRect.bottom = YDest+Height;
118
119 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
120
121 SourcePoint.x = XSrc;
122 SourcePoint.y = YSrc;
123
124 BrushOrigin.x = 0;
125 BrushOrigin.y = 0;
126
127 /* Determine surfaces to be used in the bitblt */
128 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
129 if (UsesSource)
130 {
131 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
132 BitmapSrc = BitmapDest;
133 else
134 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
135 }
136 else
137 {
138 BitmapSrc = NULL;
139 }
140
141 if (UsesPattern)
142 {
143 BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
144 if (NULL == BrushObj)
145 {
146 if (UsesSource && hDCSrc != hDCDest)
147 {
148 DC_UnlockDc(DCSrc);
149 }
150 if(BitmapDest != NULL)
151 {
152 BITMAPOBJ_UnlockBitmap(BitmapDest);
153 }
154 if(BitmapSrc != NULL && BitmapSrc != BitmapDest)
155 {
156 BITMAPOBJ_UnlockBitmap(BitmapSrc);
157 }
158 DC_UnlockDc(DCDest);
159 SetLastWin32Error(ERROR_INVALID_HANDLE);
160 return FALSE;
161 }
162 BrushOrigin = *((PPOINTL)&BrushObj->ptOrigin);
163 IntGdiInitBrushInstance(&BrushInst, BrushObj, DCDest->XlateBrush);
164 }
165 else
166 {
167 BrushObj = NULL;
168 }
169
170 /* Create the XLATEOBJ. */
171 if (UsesSource)
172 {
173 if (DCDest->w.hPalette != 0)
174 DestPalette = DCDest->w.hPalette;
175
176 if (DCSrc->w.hPalette != 0)
177 SourcePalette = DCSrc->w.hPalette;
178
179 /* KB41464 details how to convert between mono and color */
180 if (DCDest->w.bitsPerPixel == 1 && DCSrc->w.bitsPerPixel == 1)
181 {
182 XlateObj = NULL;
183 }
184 else
185 {
186 if (DCDest->w.bitsPerPixel == 1)
187 {
188 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, DCSrc->w.backgroundColor);
189 }
190 else if (DCSrc->w.bitsPerPixel == 1)
191 {
192 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, DCSrc->w.backgroundColor, DCSrc->w.textColor);
193 }
194 else
195 {
196 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
197 }
198 if (NULL == XlateObj)
199 {
200 if (UsesSource && hDCSrc != hDCDest)
201 {
202 DC_UnlockDc(DCSrc);
203 }
204 DC_UnlockDc(DCDest);
205 if(BitmapDest != NULL)
206 {
207 BITMAPOBJ_UnlockBitmap(BitmapDest);
208 }
209 if(BitmapSrc != NULL && BitmapSrc != BitmapDest)
210 {
211 BITMAPOBJ_UnlockBitmap(BitmapSrc);
212 }
213 if(BrushObj != NULL)
214 {
215 BRUSHOBJ_UnlockBrush(BrushObj);
216 }
217 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
218 return FALSE;
219 }
220 }
221 }
222
223 /* Perform the bitblt operation */
224 Status = IntEngBitBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, NULL,
225 DCDest->CombinedClip, XlateObj, &DestRect,
226 &SourcePoint, NULL,
227 BrushObj ? &BrushInst.BrushObject : NULL,
228 &BrushOrigin, ROP3_TO_ROP4(ROP));
229
230 if (UsesSource && XlateObj != NULL)
231 EngDeleteXlate(XlateObj);
232
233 if(BitmapDest != NULL)
234 {
235 BITMAPOBJ_UnlockBitmap(BitmapDest);
236 }
237 if (UsesSource && BitmapSrc != BitmapDest)
238 {
239 BITMAPOBJ_UnlockBitmap(BitmapSrc);
240 }
241 if (BrushObj != NULL)
242 {
243 BRUSHOBJ_UnlockBrush(BrushObj);
244 }
245 if (UsesSource && hDCSrc != hDCDest)
246 {
247 DC_UnlockDc(DCSrc);
248 }
249 DC_UnlockDc(DCDest);
250
251 return Status;
252 }
253
254 BOOL STDCALL
255 NtGdiTransparentBlt(
256 HDC hdcDst,
257 INT xDst,
258 INT yDst,
259 INT cxDst,
260 INT cyDst,
261 HDC hdcSrc,
262 INT xSrc,
263 INT ySrc,
264 INT cxSrc,
265 INT cySrc,
266 COLORREF TransColor)
267 {
268 PDC DCDest, DCSrc;
269 RECTL rcDest, rcSrc;
270 BITMAPOBJ *BitmapDest, *BitmapSrc;
271 XLATEOBJ *XlateObj;
272 HPALETTE SourcePalette = 0, DestPalette = 0;
273 PPALGDI PalDestGDI, PalSourceGDI;
274 USHORT PalDestMode, PalSrcMode;
275 ULONG TransparentColor = 0;
276 BOOL Ret = FALSE;
277
278 if(!(DCDest = DC_LockDc(hdcDst)))
279 {
280 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst);
281 SetLastWin32Error(ERROR_INVALID_HANDLE);
282 return FALSE;
283 }
284 if (DCDest->IsIC)
285 {
286 DC_UnlockDc(DCDest);
287 /* Yes, Windows really returns TRUE in this case */
288 return TRUE;
289 }
290
291 if((hdcDst != hdcSrc) && !(DCSrc = DC_LockDc(hdcSrc)))
292 {
293 DC_UnlockDc(DCDest);
294 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc);
295 SetLastWin32Error(ERROR_INVALID_HANDLE);
296 return FALSE;
297 }
298 if(hdcDst == hdcSrc)
299 {
300 DCSrc = DCDest;
301 }
302 if (DCSrc->IsIC)
303 {
304 DC_UnlockDc(DCSrc);
305 if(hdcDst != hdcSrc)
306 {
307 DC_UnlockDc(DCDest);
308 }
309 /* Yes, Windows really returns TRUE in this case */
310 return TRUE;
311 }
312
313 /* Offset positions */
314 xDst += DCDest->w.DCOrgX;
315 yDst += DCDest->w.DCOrgY;
316 xSrc += DCSrc->w.DCOrgX;
317 ySrc += DCSrc->w.DCOrgY;
318
319 if(DCDest->w.hPalette)
320 DestPalette = DCDest->w.hPalette;
321
322 if(DCSrc->w.hPalette)
323 SourcePalette = DCSrc->w.hPalette;
324
325 if(!(PalSourceGDI = PALETTE_LockPalette(SourcePalette)))
326 {
327 DC_UnlockDc(DCSrc);
328 DC_UnlockDc(DCDest);
329 SetLastWin32Error(ERROR_INVALID_HANDLE);
330 return FALSE;
331 }
332 if((DestPalette != SourcePalette) && !(PalDestGDI = PALETTE_LockPalette(DestPalette)))
333 {
334 PALETTE_UnlockPalette(PalSourceGDI);
335 DC_UnlockDc(DCSrc);
336 DC_UnlockDc(DCDest);
337 SetLastWin32Error(ERROR_INVALID_HANDLE);
338 return FALSE;
339 }
340 if(DestPalette != SourcePalette)
341 {
342 PalDestMode = PalDestGDI->Mode;
343 PalSrcMode = PalSourceGDI->Mode;
344 PALETTE_UnlockPalette(PalDestGDI);
345 }
346 else
347 {
348 PalDestMode = PalSrcMode = PalSourceGDI->Mode;
349 }
350 PALETTE_UnlockPalette(PalSourceGDI);
351
352 /* Translate Transparent (RGB) Color to the source palette */
353 if((XlateObj = (XLATEOBJ*)IntEngCreateXlate(PalSrcMode, PAL_RGB, SourcePalette, NULL)))
354 {
355 TransparentColor = XLATEOBJ_iXlate(XlateObj, (ULONG)TransColor);
356 EngDeleteXlate(XlateObj);
357 }
358
359 /* Create the XLATE object to convert colors between source and destination */
360 XlateObj = (XLATEOBJ*)IntEngCreateXlate(PalDestMode, PalSrcMode, DestPalette, SourcePalette);
361
362 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
363 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
364 ASSERT(BitmapDest);
365 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
366 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
367 ASSERT(BitmapSrc);
368
369 rcDest.left = xDst;
370 rcDest.top = yDst;
371 rcDest.right = rcDest.left + cxDst;
372 rcDest.bottom = rcDest.top + cyDst;
373 rcSrc.left = xSrc;
374 rcSrc.top = ySrc;
375 rcSrc.right = rcSrc.left + cxSrc;
376 rcSrc.bottom = rcSrc.top + cySrc;
377
378 if((cxDst != cxSrc) || (cyDst != cySrc))
379 {
380 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
381 goto done;
382 }
383
384 Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
385 DCDest->CombinedClip, XlateObj, &rcDest, &rcSrc,
386 TransparentColor, 0);
387
388 done:
389 BITMAPOBJ_UnlockBitmap(BitmapDest);
390 BITMAPOBJ_UnlockBitmap(BitmapSrc);
391 DC_UnlockDc(DCSrc);
392 if(hdcDst != hdcSrc)
393 {
394 DC_UnlockDc(DCDest);
395 }
396 if(XlateObj)
397 {
398 EngDeleteXlate(XlateObj);
399 }
400 return Ret;
401 }
402
403 static HBITMAP
404 IntCreateBitmapIndirect(CONST BITMAP *BM)
405 {
406 PBITMAPOBJ bmp;
407 HBITMAP hBitmap;
408 SIZEL Size;
409 UINT BitsPixel;
410
411 /* NOTE: Windows also doesn't store nr. of planes separately! */
412 BitsPixel = BM->bmBitsPixel * BM->bmPlanes;
413
414 /* Check parameters */
415 if (0 == BM->bmHeight || 0 == BM->bmWidth)
416 {
417 Size.cx = Size.cy = 1;
418 }
419 else
420 {
421 Size.cx = abs(BM->bmWidth);
422 Size.cy = abs(BM->bmHeight);
423 }
424
425 /* Create the bitmap object. */
426 hBitmap = IntCreateBitmap(Size, BM->bmWidthBytes,
427 BitmapFormat(BitsPixel, BI_RGB),
428 (BM->bmHeight < 0 ? BMF_TOPDOWN : 0) |
429 (NULL == BM->bmBits ? 0 : BMF_NOZEROINIT), NULL);
430 if (!hBitmap)
431 {
432 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
433 return 0;
434 }
435
436 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
437 Size.cx, Size.cy, BitsPixel, hBitmap);
438
439 bmp = BITMAPOBJ_LockBitmap( hBitmap );
440 if (bmp == NULL)
441 {
442 /* FIXME should we free the hBitmap or return it ?? */
443 return 0;
444 }
445
446 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
447 BITMAPOBJ_UnlockBitmap( bmp );
448
449 /*
450 * NOTE: It's ugly practice, but we are using the object even
451 * after unlocking. Since the handle is currently known only
452 * to us it should be safe.
453 */
454
455 if (NULL != BM->bmBits)
456 {
457 NtGdiSetBitmapBits(hBitmap, bmp->SurfObj.cjBits, BM->bmBits);
458 }
459
460 return hBitmap;
461 }
462
463 HBITMAP STDCALL
464 NtGdiCreateBitmap(
465 INT Width,
466 INT Height,
467 UINT Planes,
468 UINT BitsPixel,
469 IN OPTIONAL LPBYTE Bits)
470 {
471 BITMAP BM;
472
473 BM.bmType = 0;
474 BM.bmWidth = Width;
475 BM.bmHeight = Height;
476 BM.bmWidthBytes = BITMAPOBJ_GetWidthBytes(Width, Planes * BitsPixel);
477 BM.bmPlanes = Planes;
478 BM.bmBitsPixel = BitsPixel;
479 BM.bmBits = Bits;
480
481 return IntCreateBitmapIndirect(&BM);
482 }
483
484 BOOL INTERNAL_CALL
485 BITMAP_Cleanup(PVOID ObjectBody)
486 {
487 PBITMAPOBJ pBmp = (PBITMAPOBJ)ObjectBody;
488 if (pBmp->SurfObj.pvBits != NULL &&
489 (pBmp->flFlags & BITMAPOBJ_IS_APIBITMAP))
490 {
491 if (pBmp->dib == NULL)
492 {
493 if (pBmp->SurfObj.pvBits != NULL)
494 ExFreePool(pBmp->SurfObj.pvBits);
495 }
496 else
497 {
498 if (pBmp->SurfObj.pvBits != NULL)
499 EngFreeUserMem(pBmp->SurfObj.pvBits);
500 }
501 if (pBmp->hDIBPalette != NULL)
502 {
503 NtGdiDeleteObject(pBmp->hDIBPalette);
504 }
505 }
506
507 if (NULL != pBmp->BitsLock)
508 {
509 ExFreePoolWithTag(pBmp->BitsLock, TAG_BITMAPOBJ);
510 pBmp->BitsLock = NULL;
511 }
512
513 return TRUE;
514 }
515
516
517 HBITMAP FASTCALL
518 IntCreateCompatibleBitmap(
519 PDC Dc,
520 INT Width,
521 INT Height)
522 {
523 HBITMAP Bmp;
524
525 Bmp = NULL;
526
527 if ((Width >= 0x10000) || (Height >= 0x10000))
528 {
529 DPRINT1("got bad width %d or height %d, please look for reason\n", Width, Height);
530 return NULL;
531 }
532
533 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
534 if (0 == Width || 0 == Height)
535 {
536 Bmp = NtGdiCreateBitmap (1, 1, 1, 1, NULL);
537 }
538 else
539 {
540 Bmp = NtGdiCreateBitmap(Width, Height, 1, Dc->w.bitsPerPixel, NULL);
541 }
542
543 return Bmp;
544 }
545
546 HBITMAP STDCALL
547 NtGdiCreateCompatibleBitmap(
548 HDC hDC,
549 INT Width,
550 INT Height)
551 {
552 HBITMAP Bmp;
553 PDC Dc;
554
555 Dc = DC_LockDc(hDC);
556
557 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, Dc->w.bitsPerPixel);
558
559 if (NULL == Dc)
560 {
561 SetLastWin32Error(ERROR_INVALID_HANDLE);
562 return NULL;
563 }
564
565 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
566
567 DPRINT ("\t\t%04x\n", Bmp);
568 DC_UnlockDc(Dc);
569 return Bmp;
570 }
571
572 HBITMAP STDCALL
573 NtGdiCreateBitmapIndirect(CONST BITMAP *UnsafeBM)
574 {
575 BITMAP BM;
576 NTSTATUS Status = STATUS_SUCCESS;
577
578 _SEH_TRY
579 {
580 ProbeForRead(UnsafeBM, sizeof(BITMAP), 1);
581 BM = *UnsafeBM;
582 if (NULL != BM.bmBits)
583 {
584 ProbeForRead(BM.bmBits, BM.bmWidthBytes * abs(BM.bmHeight), 2);
585 }
586 }
587 _SEH_HANDLE
588 {
589 Status = _SEH_GetExceptionCode();
590 }
591 _SEH_END;
592 if(!NT_SUCCESS(Status))
593 {
594 SetLastNtError(Status);
595 return NULL;
596 }
597
598 return IntCreateBitmapIndirect(&BM);
599 }
600
601 HBITMAP STDCALL
602 NtGdiCreateDiscardableBitmap(
603 HDC hDC,
604 INT Width,
605 INT Height)
606 {
607 /* FIXME: this probably should do something else */
608 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
609 }
610
611 BOOL STDCALL
612 NtGdiExtFloodFill(
613 HDC hDC,
614 INT XStart,
615 INT YStart,
616 COLORREF Color,
617 UINT FillType)
618 {
619 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
620
621 /* lie and say we succeded */
622 return TRUE;
623 }
624
625 BOOL STDCALL
626 NtGdiFloodFill(
627 HDC hDC,
628 INT XStart,
629 INT YStart,
630 COLORREF Fill)
631 {
632 return NtGdiExtFloodFill(hDC, XStart, YStart, Fill, FLOODFILLBORDER );
633 }
634
635 BOOL STDCALL
636 NtGdiGetBitmapDimensionEx(
637 HBITMAP hBitmap,
638 LPSIZE Dimension)
639 {
640 PBITMAPOBJ bmp;
641
642 bmp = BITMAPOBJ_LockBitmap(hBitmap);
643 if (bmp == NULL)
644 {
645 return FALSE;
646 }
647
648 *Dimension = bmp->dimension;
649
650 BITMAPOBJ_UnlockBitmap(bmp);
651
652 return TRUE;
653 }
654
655 COLORREF STDCALL
656 NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
657 {
658 PDC dc = NULL;
659 COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
660 BOOL bInRect = FALSE;
661 BITMAPOBJ *BitmapObject;
662 SURFOBJ *SurfaceObject;
663 HPALETTE Pal = 0;
664 XLATEOBJ *XlateObj;
665 HBITMAP hBmpTmp;
666
667 dc = DC_LockDc (hDC);
668
669 if ( !dc )
670 {
671 SetLastWin32Error(ERROR_INVALID_HANDLE);
672 return Result;
673 }
674 if (dc->IsIC)
675 {
676 DC_UnlockDc(dc);
677 return Result;
678 }
679 XPos += dc->w.DCOrgX;
680 YPos += dc->w.DCOrgY;
681 if ( IN_RECT(dc->CombinedClip->rclBounds,XPos,YPos) )
682 {
683 bInRect = TRUE;
684 BitmapObject = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
685 SurfaceObject = &BitmapObject->SurfObj;
686 if ( BitmapObject )
687 {
688 if ( dc->w.hPalette != 0 )
689 Pal = dc->w.hPalette;
690 /* FIXME: Verify if it shouldn't be PAL_BGR! */
691 XlateObj = (XLATEOBJ*)IntEngCreateXlate ( PAL_RGB, 0, NULL, Pal );
692 if ( XlateObj )
693 {
694 // check if this DC has a DIB behind it...
695 if ( SurfaceObject->pvScan0 ) // STYPE_BITMAP == SurfaceObject->iType
696 {
697 ASSERT ( SurfaceObject->lDelta );
698 Result = XLATEOBJ_iXlate(XlateObj,
699 DibFunctionsForBitmapFormat[SurfaceObject->iBitmapFormat].DIB_GetPixel ( SurfaceObject, XPos, YPos ) );
700 }
701 EngDeleteXlate(XlateObj);
702 }
703 BITMAPOBJ_UnlockBitmap(BitmapObject);
704 }
705 }
706 DC_UnlockDc(dc);
707
708 // if Result is still CLR_INVALID, then the "quick" method above didn't work
709 if ( bInRect && Result == CLR_INVALID )
710 {
711 // FIXME: create a 1x1 32BPP DIB, and blit to it
712 HDC hDCTmp = NtGdiCreateCompatibleDC(hDC);
713 if ( hDCTmp )
714 {
715 static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
716 BITMAPINFO bi;
717 RtlMoveMemory ( &(bi.bmiHeader), &bih, sizeof(bih) );
718 hBmpTmp = NtGdiCreateDIBitmap ( hDC, &bi.bmiHeader, 0, NULL, &bi, DIB_RGB_COLORS );
719 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
720 if ( hBmpTmp )
721 {
722 HBITMAP hBmpOld = (HBITMAP)NtGdiSelectObject ( hDCTmp, hBmpTmp );
723 if ( hBmpOld )
724 {
725 PBITMAPOBJ bmpobj;
726
727 NtGdiBitBlt ( hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0 );
728 NtGdiSelectObject ( hDCTmp, hBmpOld );
729
730 // our bitmap is no longer selected, so we can access it's stuff...
731 bmpobj = BITMAPOBJ_LockBitmap ( hBmpTmp );
732 if ( bmpobj )
733 {
734 Result = *(COLORREF*)bmpobj->SurfObj.pvScan0;
735 BITMAPOBJ_UnlockBitmap ( bmpobj );
736 }
737 }
738 NtGdiDeleteObject ( hBmpTmp );
739 }
740 NtGdiDeleteObjectApp ( hDCTmp );
741 }
742 }
743
744 return Result;
745 }
746
747 /***********************************************************************
748 * MaskBlt
749 * Ported from WINE by sedwards 11-4-03
750 *
751 * Someone thought it would be faster to do it here and then switch back
752 * to GDI32. I dunno. Write a test and let me know.
753 */
754
755 static __inline BYTE
756 SwapROP3_SrcDst(BYTE bRop3)
757 {
758 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
759 }
760
761 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
762 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
763 #define DSTCOPY 0x00AA0029
764 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
765
766 BOOL STDCALL
767 NtGdiMaskBlt (
768 HDC hdcDest, INT nXDest, INT nYDest,
769 INT nWidth, INT nHeight, HDC hdcSrc,
770 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
771 INT xMask, INT yMask, DWORD dwRop,
772 IN DWORD crBackColor)
773 {
774 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
775 HDC hDCMask, hDC1, hDC2;
776 static const DWORD ROP3Table[256] =
777 {
778 0x00000042, 0x00010289,
779 0x00020C89, 0x000300AA,
780 0x00040C88, 0x000500A9,
781 0x00060865, 0x000702C5,
782 0x00080F08, 0x00090245,
783 0x000A0329, 0x000B0B2A,
784 0x000C0324, 0x000D0B25,
785 0x000E08A5, 0x000F0001,
786 0x00100C85, 0x001100A6,
787 0x00120868, 0x001302C8,
788 0x00140869, 0x001502C9,
789 0x00165CCA, 0x00171D54,
790 0x00180D59, 0x00191CC8,
791 0x001A06C5, 0x001B0768,
792 0x001C06CA, 0x001D0766,
793 0x001E01A5, 0x001F0385,
794 0x00200F09, 0x00210248,
795 0x00220326, 0x00230B24,
796 0x00240D55, 0x00251CC5,
797 0x002606C8, 0x00271868,
798 0x00280369, 0x002916CA,
799 0x002A0CC9, 0x002B1D58,
800 0x002C0784, 0x002D060A,
801 0x002E064A, 0x002F0E2A,
802 0x0030032A, 0x00310B28,
803 0x00320688, 0x00330008,
804 0x003406C4, 0x00351864,
805 0x003601A8, 0x00370388,
806 0x0038078A, 0x00390604,
807 0x003A0644, 0x003B0E24,
808 0x003C004A, 0x003D18A4,
809 0x003E1B24, 0x003F00EA,
810 0x00400F0A, 0x00410249,
811 0x00420D5D, 0x00431CC4,
812 0x00440328, 0x00450B29,
813 0x004606C6, 0x0047076A,
814 0x00480368, 0x004916C5,
815 0x004A0789, 0x004B0605,
816 0x004C0CC8, 0x004D1954,
817 0x004E0645, 0x004F0E25,
818 0x00500325, 0x00510B26,
819 0x005206C9, 0x00530764,
820 0x005408A9, 0x00550009,
821 0x005601A9, 0x00570389,
822 0x00580785, 0x00590609,
823 0x005A0049, 0x005B18A9,
824 0x005C0649, 0x005D0E29,
825 0x005E1B29, 0x005F00E9,
826 0x00600365, 0x006116C6,
827 0x00620786, 0x00630608,
828 0x00640788, 0x00650606,
829 0x00660046, 0x006718A8,
830 0x006858A6, 0x00690145,
831 0x006A01E9, 0x006B178A,
832 0x006C01E8, 0x006D1785,
833 0x006E1E28, 0x006F0C65,
834 0x00700CC5, 0x00711D5C,
835 0x00720648, 0x00730E28,
836 0x00740646, 0x00750E26,
837 0x00761B28, 0x007700E6,
838 0x007801E5, 0x00791786,
839 0x007A1E29, 0x007B0C68,
840 0x007C1E24, 0x007D0C69,
841 0x007E0955, 0x007F03C9,
842 0x008003E9, 0x00810975,
843 0x00820C49, 0x00831E04,
844 0x00840C48, 0x00851E05,
845 0x008617A6, 0x008701C5,
846 0x008800C6, 0x00891B08,
847 0x008A0E06, 0x008B0666,
848 0x008C0E08, 0x008D0668,
849 0x008E1D7C, 0x008F0CE5,
850 0x00900C45, 0x00911E08,
851 0x009217A9, 0x009301C4,
852 0x009417AA, 0x009501C9,
853 0x00960169, 0x0097588A,
854 0x00981888, 0x00990066,
855 0x009A0709, 0x009B07A8,
856 0x009C0704, 0x009D07A6,
857 0x009E16E6, 0x009F0345,
858 0x00A000C9, 0x00A11B05,
859 0x00A20E09, 0x00A30669,
860 0x00A41885, 0x00A50065,
861 0x00A60706, 0x00A707A5,
862 0x00A803A9, 0x00A90189,
863 0x00AA0029, 0x00AB0889,
864 0x00AC0744, 0x00AD06E9,
865 0x00AE0B06, 0x00AF0229,
866 0x00B00E05, 0x00B10665,
867 0x00B21974, 0x00B30CE8,
868 0x00B4070A, 0x00B507A9,
869 0x00B616E9, 0x00B70348,
870 0x00B8074A, 0x00B906E6,
871 0x00BA0B09, 0x00BB0226,
872 0x00BC1CE4, 0x00BD0D7D,
873 0x00BE0269, 0x00BF08C9,
874 0x00C000CA, 0x00C11B04,
875 0x00C21884, 0x00C3006A,
876 0x00C40E04, 0x00C50664,
877 0x00C60708, 0x00C707AA,
878 0x00C803A8, 0x00C90184,
879 0x00CA0749, 0x00CB06E4,
880 0x00CC0020, 0x00CD0888,
881 0x00CE0B08, 0x00CF0224,
882 0x00D00E0A, 0x00D1066A,
883 0x00D20705, 0x00D307A4,
884 0x00D41D78, 0x00D50CE9,
885 0x00D616EA, 0x00D70349,
886 0x00D80745, 0x00D906E8,
887 0x00DA1CE9, 0x00DB0D75,
888 0x00DC0B04, 0x00DD0228,
889 0x00DE0268, 0x00DF08C8,
890 0x00E003A5, 0x00E10185,
891 0x00E20746, 0x00E306EA,
892 0x00E40748, 0x00E506E5,
893 0x00E61CE8, 0x00E70D79,
894 0x00E81D74, 0x00E95CE6,
895 0x00EA02E9, 0x00EB0849,
896 0x00EC02E8, 0x00ED0848,
897 0x00EE0086, 0x00EF0A08,
898 0x00F00021, 0x00F10885,
899 0x00F20B05, 0x00F3022A,
900 0x00F40B0A, 0x00F50225,
901 0x00F60265, 0x00F708C5,
902 0x00F802E5, 0x00F90845,
903 0x00FA0089, 0x00FB0A09,
904 0x00FC008A, 0x00FD0A0A,
905 0x00FE02A9, 0x00FF0062,
906 };
907
908 if (!hbmMask)
909 return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0, 0);
910
911 /* 1. make mask bitmap's dc */
912 hDCMask = NtGdiCreateCompatibleDC(hdcDest);
913 hOldMaskBitmap = (HBITMAP)NtGdiSelectObject(hDCMask, hbmMask);
914
915 /* 2. make masked Background bitmap */
916
917 /* 2.1 make bitmap */
918 hDC1 = NtGdiCreateCompatibleDC(hdcDest);
919 hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
920 hOldBitmap2 = (HBITMAP)NtGdiSelectObject(hDC1, hBitmap2);
921
922 /* 2.2 draw dest bitmap and mask */
923 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0);
924 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0);
925 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE, 0, 0);
926
927 /* 3. make masked Foreground bitmap */
928
929 /* 3.1 make bitmap */
930 hDC2 = NtGdiCreateCompatibleDC(hdcDest);
931 hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
932 hOldBitmap3 = (HBITMAP)NtGdiSelectObject(hDC2, hBitmap3);
933
934 /* 3.2 draw src bitmap and mask */
935 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0);
936 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0);
937 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND, 0, 0);
938
939 /* 4. combine two bitmap and copy it to hdcDest */
940 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT, 0, 0);
941 NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY, 0, 0);
942
943 /* 5. restore all object */
944 NtGdiSelectObject(hDCMask, hOldMaskBitmap);
945 NtGdiSelectObject(hDC1, hOldBitmap2);
946 NtGdiSelectObject(hDC2, hOldBitmap3);
947
948 /* 6. delete all temp object */
949 NtGdiDeleteObject(hBitmap2);
950 NtGdiDeleteObject(hBitmap3);
951
952 NtGdiDeleteObjectApp(hDC1);
953 NtGdiDeleteObjectApp(hDC2);
954 NtGdiDeleteObjectApp(hDCMask);
955
956 return TRUE;
957 }
958
959 BOOL
960 APIENTRY
961 NtGdiPlgBlt(
962 IN HDC hdcTrg,
963 IN LPPOINT pptlTrg,
964 IN HDC hdcSrc,
965 IN INT xSrc,
966 IN INT ySrc,
967 IN INT cxSrc,
968 IN INT cySrc,
969 IN HBITMAP hbmMask,
970 IN INT xMask,
971 IN INT yMask,
972 IN DWORD crBackColor)
973 {
974 UNIMPLEMENTED;
975 return FALSE;
976 }
977
978 LONG STDCALL
979 NtGdiSetBitmapBits(
980 HBITMAP hBitmap,
981 DWORD Bytes,
982 IN PBYTE Bits)
983 {
984 LONG height, ret;
985 PBITMAPOBJ bmp;
986
987 bmp = BITMAPOBJ_LockBitmap(hBitmap);
988 if (bmp == NULL || Bits == NULL)
989 {
990 return 0;
991 }
992
993 if (Bytes < 0)
994 {
995 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes );
996 Bytes = -Bytes;
997 }
998
999 /* Only get entire lines */
1000 height = Bytes / abs(bmp->SurfObj.lDelta);
1001 if (height > bmp->SurfObj.sizlBitmap.cy)
1002 {
1003 height = bmp->SurfObj.sizlBitmap.cy;
1004 }
1005 Bytes = height * abs(bmp->SurfObj.lDelta);
1006 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
1007 hBitmap,
1008 Bytes,
1009 Bits,
1010 bmp->SurfObj.sizlBitmap.cx,
1011 bmp->SurfObj.sizlBitmap.cy,
1012 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat),
1013 height);
1014
1015 #if 0
1016 /* FIXME: call DDI specific function here if available */
1017 if(bmp->DDBitmap)
1018 {
1019 DPRINT ("Calling device specific BitmapBits\n");
1020 if (bmp->DDBitmap->funcs->pBitmapBits)
1021 {
1022 ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET);
1023 }
1024 else
1025 {
1026 DPRINT ("BitmapBits == NULL??\n");
1027 ret = 0;
1028 }
1029 }
1030 else
1031 #endif
1032 {
1033 memcpy(bmp->SurfObj.pvBits, Bits, Bytes);
1034 ret = Bytes;
1035 }
1036
1037 BITMAPOBJ_UnlockBitmap(bmp);
1038
1039 return ret;
1040 }
1041
1042 BOOL STDCALL
1043 NtGdiSetBitmapDimensionEx(
1044 HBITMAP hBitmap,
1045 INT Width,
1046 INT Height,
1047 LPSIZE Size)
1048 {
1049 PBITMAPOBJ bmp;
1050
1051 bmp = BITMAPOBJ_LockBitmap(hBitmap);
1052 if (bmp == NULL)
1053 {
1054 return FALSE;
1055 }
1056
1057 if (Size)
1058 {
1059 *Size = bmp->dimension;
1060 }
1061 bmp->dimension.cx = Width;
1062 bmp->dimension.cy = Height;
1063
1064 BITMAPOBJ_UnlockBitmap (bmp);
1065
1066 return TRUE;
1067 }
1068
1069 COLORREF STDCALL
1070 NtGdiSetPixel(
1071 HDC hDC,
1072 INT X,
1073 INT Y,
1074 COLORREF Color)
1075 {
1076
1077 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1078
1079
1080 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1081
1082 if (NtGdiSetPixelV(hDC,X,Y,Color))
1083 {
1084 Color = NtGdiGetPixel(hDC,X,Y);
1085 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1086 return Color;
1087 }
1088
1089 Color = ((COLORREF) -1);
1090 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1091 return Color;
1092 }
1093
1094 BOOL STDCALL
1095 NtGdiSetPixelV(
1096 HDC hDC,
1097 INT X,
1098 INT Y,
1099 COLORREF Color)
1100 {
1101 HBRUSH NewBrush = NtGdiCreateSolidBrush(Color, NULL);
1102 HGDIOBJ OldBrush;
1103
1104 if (NewBrush == NULL)
1105 return(FALSE);
1106 OldBrush = NtGdiSelectObject(hDC, NewBrush);
1107 if (OldBrush == NULL)
1108 {
1109 NtGdiDeleteObject(NewBrush);
1110 return(FALSE);
1111 }
1112 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
1113 NtGdiSelectObject(hDC, OldBrush);
1114 NtGdiDeleteObject(NewBrush);
1115 return TRUE;
1116 }
1117
1118 BOOL STDCALL
1119 NtGdiStretchBlt(
1120 HDC hDCDest,
1121 INT XOriginDest,
1122 INT YOriginDest,
1123 INT WidthDest,
1124 INT HeightDest,
1125 HDC hDCSrc,
1126 INT XOriginSrc,
1127 INT YOriginSrc,
1128 INT WidthSrc,
1129 INT HeightSrc,
1130 DWORD ROP,
1131 IN DWORD dwBackColor)
1132 {
1133 PDC DCDest = NULL;
1134 PDC DCSrc = NULL;
1135 BITMAPOBJ *BitmapDest, *BitmapSrc;
1136 RECTL DestRect;
1137 RECTL SourceRect;
1138 BOOL Status;
1139 XLATEOBJ *XlateObj = NULL;
1140 HPALETTE SourcePalette = 0, DestPalette = 0;
1141 PGDIBRUSHOBJ BrushObj;
1142 BOOL UsesSource = ((ROP & 0xCC0000) >> 2) != (ROP & 0x330000);
1143 BOOL UsesPattern = ((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
1144
1145 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
1146 {
1147 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1148 return FALSE;
1149 }
1150 DCDest = DC_LockDc(hDCDest);
1151 if (NULL == DCDest)
1152 {
1153 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
1154 SetLastWin32Error(ERROR_INVALID_HANDLE);
1155 return FALSE;
1156 }
1157 if (DCDest->IsIC)
1158 {
1159 DC_UnlockDc(DCDest);
1160 /* Yes, Windows really returns TRUE in this case */
1161 return TRUE;
1162 }
1163
1164 if (UsesSource)
1165 {
1166 if (hDCSrc != hDCDest)
1167 {
1168 DCSrc = DC_LockDc(hDCSrc);
1169 if (NULL == DCSrc)
1170 {
1171 DC_UnlockDc(DCDest);
1172 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
1173 SetLastWin32Error(ERROR_INVALID_HANDLE);
1174 return FALSE;
1175 }
1176 if (DCSrc->IsIC)
1177 {
1178 DC_UnlockDc(DCSrc);
1179 DC_UnlockDc(DCDest);
1180 /* Yes, Windows really returns TRUE in this case */
1181 return TRUE;
1182 }
1183 }
1184 else
1185 {
1186 DCSrc = DCDest;
1187 }
1188 }
1189 else
1190 {
1191 DCSrc = NULL;
1192 }
1193
1194 /* Offset the destination and source by the origin of their DCs. */
1195 XOriginDest += DCDest->w.DCOrgX;
1196 YOriginDest += DCDest->w.DCOrgY;
1197 if (UsesSource)
1198 {
1199 XOriginSrc += DCSrc->w.DCOrgX;
1200 YOriginSrc += DCSrc->w.DCOrgY;
1201 }
1202
1203 DestRect.left = XOriginDest;
1204 DestRect.top = YOriginDest;
1205 DestRect.right = XOriginDest+WidthDest;
1206 DestRect.bottom = YOriginDest+HeightDest;
1207
1208 SourceRect.left = XOriginSrc;
1209 SourceRect.top = YOriginSrc;
1210 SourceRect.right = XOriginSrc+WidthSrc;
1211 SourceRect.bottom = YOriginSrc+HeightSrc;
1212
1213 /* Determine surfaces to be used in the bitblt */
1214 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
1215 if (UsesSource)
1216 {
1217 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
1218 BitmapSrc = BitmapDest;
1219 else
1220 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
1221 }
1222 else
1223 {
1224 BitmapSrc = NULL;
1225 }
1226
1227 if ( UsesSource )
1228 {
1229 int sw = BitmapSrc->SurfObj.sizlBitmap.cx;
1230 int sh = BitmapSrc->SurfObj.sizlBitmap.cy;
1231 if ( SourceRect.left < 0 )
1232 {
1233 DestRect.left = DestRect.right - (DestRect.right-DestRect.left) * (SourceRect.right)/abs(SourceRect.right-SourceRect.left);
1234 SourceRect.left = 0;
1235 }
1236 if ( SourceRect.top < 0 )
1237 {
1238 DestRect.top = DestRect.bottom - (DestRect.bottom-DestRect.top) * (SourceRect.bottom)/abs(SourceRect.bottom-SourceRect.top);
1239 SourceRect.top = 0;
1240 }
1241 if ( SourceRect.right < -1 )
1242 {
1243 DestRect.right = DestRect.left + (DestRect.right-DestRect.left) * (-1-SourceRect.left)/abs(SourceRect.right-SourceRect.left);
1244 SourceRect.right = -1;
1245 }
1246 if ( SourceRect.bottom < -1 )
1247 {
1248 DestRect.bottom = DestRect.top + (DestRect.bottom-DestRect.top) * (-1-SourceRect.top)/abs(SourceRect.bottom-SourceRect.top);
1249 SourceRect.bottom = -1;
1250 }
1251 if ( SourceRect.right > sw )
1252 {
1253 DestRect.right = DestRect.left + (DestRect.right-DestRect.left) * abs(sw-SourceRect.left) / abs(SourceRect.right-SourceRect.left);
1254 SourceRect.right = sw;
1255 }
1256 if ( SourceRect.bottom > sh )
1257 {
1258 DestRect.bottom = DestRect.top + (DestRect.bottom-DestRect.top) * abs(sh-SourceRect.top) / abs(SourceRect.bottom-SourceRect.top);
1259 SourceRect.bottom = sh;
1260 }
1261 sw--;
1262 sh--;
1263 if ( SourceRect.left > sw )
1264 {
1265 DestRect.left = DestRect.right - (DestRect.right-DestRect.left) * (SourceRect.right-sw) / abs(SourceRect.right-SourceRect.left);
1266 SourceRect.left = 0;
1267 }
1268 if ( SourceRect.top > sh )
1269 {
1270 DestRect.top = DestRect.bottom - (DestRect.bottom-DestRect.top) * (SourceRect.bottom-sh) / abs(SourceRect.bottom-SourceRect.top);
1271 SourceRect.top = 0;
1272 }
1273 if (0 == (DestRect.right-DestRect.left) || 0 == (DestRect.bottom-DestRect.top) || 0 == (SourceRect.right-SourceRect.left) || 0 == (SourceRect.bottom-SourceRect.top))
1274 {
1275 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1276 Status = FALSE;
1277 goto failed;
1278 }
1279 }
1280
1281 if (UsesPattern)
1282 {
1283 BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
1284 if (NULL == BrushObj)
1285 {
1286 if (UsesSource && hDCSrc != hDCDest)
1287 {
1288 DC_UnlockDc(DCSrc);
1289 }
1290 DC_UnlockDc(DCDest);
1291 SetLastWin32Error(ERROR_INVALID_HANDLE);
1292 return FALSE;
1293 }
1294 }
1295 else
1296 {
1297 BrushObj = NULL;
1298 }
1299
1300 /* Create the XLATEOBJ. */
1301 if (UsesSource)
1302 {
1303 if (DCDest->w.hPalette != 0)
1304 DestPalette = DCDest->w.hPalette;
1305
1306 if (DCSrc->w.hPalette != 0)
1307 SourcePalette = DCSrc->w.hPalette;
1308
1309 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1310 XlateObj = (XLATEOBJ*)IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
1311 if (NULL == XlateObj)
1312 {
1313 if (UsesSource && hDCSrc != hDCDest)
1314 {
1315 DC_UnlockDc(DCSrc);
1316 }
1317 DC_UnlockDc(DCDest);
1318 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1319 return FALSE;
1320 }
1321 }
1322
1323 /* Perform the bitblt operation */
1324 Status = IntEngStretchBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
1325 NULL, DCDest->CombinedClip, XlateObj,
1326 &DestRect, &SourceRect, NULL, NULL, NULL,
1327 COLORONCOLOR);
1328
1329 if (UsesSource)
1330 EngDeleteXlate(XlateObj);
1331 if (UsesPattern)
1332 {
1333 BRUSHOBJ_UnlockBrush(BrushObj);
1334 }
1335 failed:
1336 if (UsesSource && DCSrc->w.hBitmap != DCDest->w.hBitmap)
1337 {
1338 BITMAPOBJ_UnlockBitmap(BitmapSrc);
1339 }
1340 BITMAPOBJ_UnlockBitmap(BitmapDest);
1341 if (UsesSource && hDCSrc != hDCDest)
1342 {
1343 DC_UnlockDc(DCSrc);
1344 }
1345 DC_UnlockDc(DCDest);
1346
1347 return Status;
1348 }
1349
1350 BOOL STDCALL
1351 NtGdiAlphaBlend(
1352 HDC hDCDest,
1353 LONG XOriginDest,
1354 LONG YOriginDest,
1355 LONG WidthDest,
1356 LONG HeightDest,
1357 HDC hDCSrc,
1358 LONG XOriginSrc,
1359 LONG YOriginSrc,
1360 LONG WidthSrc,
1361 LONG HeightSrc,
1362 BLENDFUNCTION BlendFunc)
1363 {
1364 PDC DCDest = NULL;
1365 PDC DCSrc = NULL;
1366 BITMAPOBJ *BitmapDest, *BitmapSrc;
1367 RECTL DestRect, SourceRect;
1368 BOOL Status;
1369 XLATEOBJ *XlateObj;
1370 BLENDOBJ BlendObj;
1371 HPALETTE SourcePalette = 0, DestPalette = 0;
1372 BlendObj.BlendFunction = BlendFunc;
1373
1374 DCDest = DC_LockDc(hDCDest);
1375 if (NULL == DCDest)
1376 {
1377 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest);
1378 SetLastWin32Error(ERROR_INVALID_HANDLE);
1379 return FALSE;
1380 }
1381 if (DCDest->IsIC)
1382 {
1383 DC_UnlockDc(DCDest);
1384 /* Yes, Windows really returns TRUE in this case */
1385 return TRUE;
1386 }
1387
1388 if (hDCSrc != hDCDest)
1389 {
1390 DCSrc = DC_LockDc(hDCSrc);
1391 if (NULL == DCSrc)
1392 {
1393 DC_UnlockDc(DCDest);
1394 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc);
1395 SetLastWin32Error(ERROR_INVALID_HANDLE);
1396 return FALSE;
1397 }
1398 if (DCSrc->IsIC)
1399 {
1400 DC_UnlockDc(DCSrc);
1401 DC_UnlockDc(DCDest);
1402 /* Yes, Windows really returns TRUE in this case */
1403 return TRUE;
1404 }
1405 }
1406 else
1407 {
1408 DCSrc = DCDest;
1409 }
1410
1411 /* Offset the destination and source by the origin of their DCs. */
1412 XOriginDest += DCDest->w.DCOrgX;
1413 YOriginDest += DCDest->w.DCOrgY;
1414 XOriginSrc += DCSrc->w.DCOrgX;
1415 YOriginSrc += DCSrc->w.DCOrgY;
1416
1417 DestRect.left = XOriginDest;
1418 DestRect.top = YOriginDest;
1419 DestRect.right = XOriginDest + WidthDest;
1420 DestRect.bottom = YOriginDest + HeightDest;
1421
1422 SourceRect.left = XOriginSrc;
1423 SourceRect.top = YOriginSrc;
1424 SourceRect.right = XOriginSrc + WidthSrc;
1425 SourceRect.bottom = YOriginSrc + HeightSrc;
1426
1427 /* Determine surfaces to be used in the bitblt */
1428 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
1429 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
1430 BitmapSrc = BitmapDest;
1431 else
1432 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
1433
1434 /* Create the XLATEOBJ. */
1435 if (DCDest->w.hPalette != 0)
1436 DestPalette = DCDest->w.hPalette;
1437 if (DCSrc->w.hPalette != 0)
1438 SourcePalette = DCSrc->w.hPalette;
1439
1440 /* KB41464 details how to convert between mono and color */
1441 if (DCDest->w.bitsPerPixel == 1 && DCSrc->w.bitsPerPixel == 1)
1442 {
1443 XlateObj = NULL;
1444 }
1445 else
1446 {
1447 if (DCDest->w.bitsPerPixel == 1)
1448 {
1449 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, DCSrc->w.backgroundColor);
1450 }
1451 else if (DCSrc->w.bitsPerPixel == 1)
1452 {
1453 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, DCSrc->w.backgroundColor, DCSrc->w.textColor);
1454 }
1455 else
1456 {
1457 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
1458 }
1459 if (NULL == XlateObj)
1460 {
1461 BITMAPOBJ_UnlockBitmap(BitmapDest);
1462 if (BitmapSrc != BitmapDest)
1463 BITMAPOBJ_UnlockBitmap(BitmapSrc);
1464 DC_UnlockDc(DCDest);
1465 if (hDCSrc != hDCDest)
1466 DC_UnlockDc(DCSrc);
1467 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1468 return FALSE;
1469 }
1470 }
1471
1472 /* Perform the alpha blend operation */
1473 Status = IntEngAlphaBlend(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
1474 DCDest->CombinedClip, XlateObj,
1475 &DestRect, &SourceRect, &BlendObj);
1476
1477 if (XlateObj != NULL)
1478 EngDeleteXlate(XlateObj);
1479
1480 BITMAPOBJ_UnlockBitmap(BitmapDest);
1481 if (BitmapSrc != BitmapDest)
1482 BITMAPOBJ_UnlockBitmap(BitmapSrc);
1483 DC_UnlockDc(DCDest);
1484 if (hDCSrc != hDCDest)
1485 DC_UnlockDc(DCSrc);
1486
1487 return Status;
1488 }
1489
1490 /* Internal Functions */
1491
1492 INT FASTCALL
1493 BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
1494 {
1495 #if 0
1496 switch(bpp)
1497 {
1498 case 1:
1499 return 2 * ((bmWidth+15) >> 4);
1500
1501 case 24:
1502 bmWidth *= 3; /* fall through */
1503 case 8:
1504 return bmWidth + (bmWidth & 1);
1505
1506 case 32:
1507 return bmWidth * 4;
1508
1509 case 16:
1510 case 15:
1511 return bmWidth * 2;
1512
1513 case 4:
1514 return 2 * ((bmWidth+3) >> 2);
1515
1516 default:
1517 DPRINT ("stub");
1518 }
1519
1520 return -1;
1521 #endif
1522
1523 return ((bmWidth * bpp + 15) & ~15) >> 3;
1524 }
1525
1526 HBITMAP FASTCALL
1527 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
1528 {
1529 HBITMAP res;
1530 BITMAP bm;
1531 BITMAPOBJ *Bitmap;
1532
1533 if (hBitmap == NULL)
1534 return 0;
1535
1536 Bitmap = GDIOBJ_LockObj(GdiHandleTable, hBitmap, GDI_OBJECT_TYPE_BITMAP);
1537 if (Bitmap == NULL)
1538 return 0;
1539
1540 BITMAP_GetObject(Bitmap, sizeof(BITMAP), &bm);
1541 bm.bmBits = NULL;
1542 if (Bitmap->SurfObj.lDelta >= 0)
1543 bm.bmHeight = -bm.bmHeight;
1544
1545 res = IntCreateBitmapIndirect(&bm);
1546 if(res)
1547 {
1548 PBYTE buf;
1549
1550 buf = ExAllocatePoolWithTag (PagedPool, bm.bmWidthBytes * abs(bm.bmHeight), TAG_BITMAP);
1551 NtGdiGetBitmapBits (hBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
1552 NtGdiSetBitmapBits (res, bm.bmWidthBytes * abs(bm.bmHeight), buf);
1553 ExFreePool (buf);
1554 }
1555
1556 GDIOBJ_UnlockObjByPtr(GdiHandleTable, Bitmap);
1557
1558 return res;
1559 }
1560
1561 INT STDCALL
1562 BITMAP_GetObject(BITMAPOBJ * bmp, INT Count, LPVOID buffer)
1563 {
1564 if( buffer == NULL ) return sizeof(BITMAP);
1565 if (Count < sizeof(BITMAP)) return 0;
1566
1567 if(bmp->dib)
1568 {
1569
1570 if(Count < (INT) sizeof(DIBSECTION))
1571 {
1572 if (Count > (INT) sizeof(BITMAP)) Count = sizeof(BITMAP);
1573 }
1574 else
1575 {
1576 if (Count > (INT) sizeof(DIBSECTION)) Count = sizeof(DIBSECTION);
1577 }
1578 memcpy(buffer, bmp->dib, Count);
1579 return Count;
1580 }
1581 else
1582 {
1583 BITMAP Bitmap;
1584 if (Count > (INT) sizeof(BITMAP)) Count = sizeof(BITMAP);
1585 Bitmap.bmType = 0;
1586 Bitmap.bmWidth = bmp->SurfObj.sizlBitmap.cx;
1587 Bitmap.bmHeight = bmp->SurfObj.sizlBitmap.cy;
1588 Bitmap.bmWidthBytes = abs(bmp->SurfObj.lDelta);
1589 Bitmap.bmPlanes = 1;
1590 Bitmap.bmBitsPixel = BitsPerFormat(bmp->SurfObj.iBitmapFormat);
1591 //Bitmap.bmBits = bmp->SurfObj.pvBits;
1592 Bitmap.bmBits = NULL; /* not set accoring wine test confirm in win2k */
1593 memcpy(buffer, &Bitmap, Count);
1594 return Count;
1595 }
1596 }
1597 /* EOF */