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