rename NtGdiGetBitmapDimensionEx to NtGdiGetBitmapDimension, update ntgdibad.h
[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->Dc_Attr.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->Dc_Attr.crBackgroundClr);
189 }
190 else if (DCSrc->w.bitsPerPixel == 1)
191 {
192 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, DCSrc->Dc_Attr.crBackgroundClr, DCSrc->Dc_Attr.crForegroundClr);
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 HBITMAP STDCALL
404 NtGdiCreateBitmap(
405 INT Width,
406 INT Height,
407 UINT Planes,
408 UINT BitsPixel,
409 IN OPTIONAL LPBYTE pUnsafeBits)
410 {
411 PBITMAPOBJ bmp;
412 HBITMAP hBitmap;
413 SIZEL Size;
414 LONG WidthBytes;
415
416 /* NOTE: Windows also doesn't store nr. of planes separately! */
417 BitsPixel = BitsPixel * Planes;
418 WidthBytes = BITMAPOBJ_GetWidthBytes(Width, BitsPixel);
419
420 /* Check parameters */
421 if (0 == Height || 0 == Width)
422 {
423 Size.cx = Size.cy = 1;
424 }
425 else
426 {
427 Size.cx = abs(Width);
428 Size.cy = abs(Height);
429 }
430
431 /* Create the bitmap object. */
432 hBitmap = IntCreateBitmap(Size, WidthBytes,
433 BitmapFormat(BitsPixel, BI_RGB),
434 (Height < 0 ? BMF_TOPDOWN : 0) |
435 (NULL == pUnsafeBits ? 0 : BMF_NOZEROINIT), NULL);
436 if (!hBitmap)
437 {
438 DPRINT("NtGdiCreateBitmap: returned 0\n");
439 return 0;
440 }
441
442 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
443 Size.cx, Size.cy, BitsPixel, hBitmap);
444
445 bmp = BITMAPOBJ_LockBitmap( hBitmap );
446 if (bmp == NULL)
447 {
448 /* FIXME should we free the hBitmap or return it ?? */
449 return 0;
450 }
451
452 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
453
454 if (NULL != pUnsafeBits)
455 {
456 _SEH_TRY
457 {
458 ProbeForRead(pUnsafeBits, bmp->SurfObj.cjBits, 1);
459 IntSetBitmapBits(bmp, bmp->SurfObj.cjBits, pUnsafeBits);
460 }
461 _SEH_HANDLE
462 {
463 }
464 _SEH_END
465 }
466
467 BITMAPOBJ_UnlockBitmap( bmp );
468
469 return hBitmap;
470 }
471
472 BOOL INTERNAL_CALL
473 BITMAP_Cleanup(PVOID ObjectBody)
474 {
475 PBITMAPOBJ pBmp = (PBITMAPOBJ)ObjectBody;
476 if (pBmp->SurfObj.pvBits != NULL &&
477 (pBmp->flFlags & BITMAPOBJ_IS_APIBITMAP))
478 {
479 if (pBmp->dib == NULL)
480 {
481 if (pBmp->SurfObj.pvBits != NULL)
482 ExFreePool(pBmp->SurfObj.pvBits);
483 }
484 else
485 {
486 if (pBmp->SurfObj.pvBits != NULL)
487 EngFreeUserMem(pBmp->SurfObj.pvBits);
488 }
489 if (pBmp->hDIBPalette != NULL)
490 {
491 NtGdiDeleteObject(pBmp->hDIBPalette);
492 }
493 }
494
495 if (NULL != pBmp->BitsLock)
496 {
497 ExFreePoolWithTag(pBmp->BitsLock, TAG_BITMAPOBJ);
498 pBmp->BitsLock = NULL;
499 }
500
501 return TRUE;
502 }
503
504
505 HBITMAP FASTCALL
506 IntCreateCompatibleBitmap(
507 PDC Dc,
508 INT Width,
509 INT Height)
510 {
511 HBITMAP Bmp;
512
513 Bmp = NULL;
514
515 if ((Width >= 0x10000) || (Height >= 0x10000))
516 {
517 DPRINT1("got bad width %d or height %d, please look for reason\n", Width, Height);
518 return NULL;
519 }
520
521 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
522 if (0 == Width || 0 == Height)
523 {
524 Bmp = NtGdiCreateBitmap (1, 1, 1, 1, NULL);
525 }
526 else
527 {
528 Bmp = NtGdiCreateBitmap(Width, Height, 1, Dc->w.bitsPerPixel, NULL);
529 }
530
531 return Bmp;
532 }
533
534 HBITMAP STDCALL
535 NtGdiCreateCompatibleBitmap(
536 HDC hDC,
537 INT Width,
538 INT Height)
539 {
540 HBITMAP Bmp;
541 PDC Dc;
542
543 Dc = DC_LockDc(hDC);
544
545 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, Dc->w.bitsPerPixel);
546
547 if (NULL == Dc)
548 {
549 SetLastWin32Error(ERROR_INVALID_HANDLE);
550 return NULL;
551 }
552
553 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
554
555 DPRINT ("\t\t%04x\n", Bmp);
556 DC_UnlockDc(Dc);
557 return Bmp;
558 }
559
560 BOOL STDCALL
561 NtGdiExtFloodFill(
562 HDC hDC,
563 INT XStart,
564 INT YStart,
565 COLORREF Color,
566 UINT FillType)
567 {
568 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
569
570 /* lie and say we succeded */
571 return TRUE;
572 }
573
574 BOOL STDCALL
575 NtGdiGetBitmapDimension(
576 HBITMAP hBitmap,
577 LPSIZE Dimension)
578 {
579 PBITMAPOBJ bmp;
580
581 bmp = BITMAPOBJ_LockBitmap(hBitmap);
582 if (bmp == NULL)
583 {
584 return FALSE;
585 }
586
587 *Dimension = bmp->dimension;
588
589 BITMAPOBJ_UnlockBitmap(bmp);
590
591 return TRUE;
592 }
593
594 COLORREF STDCALL
595 NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
596 {
597 PDC dc = NULL;
598 COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
599 BOOL bInRect = FALSE;
600 BITMAPOBJ *BitmapObject;
601 SURFOBJ *SurfaceObject;
602 HPALETTE Pal = 0;
603 XLATEOBJ *XlateObj;
604 HBITMAP hBmpTmp;
605
606 dc = DC_LockDc (hDC);
607
608 if ( !dc )
609 {
610 SetLastWin32Error(ERROR_INVALID_HANDLE);
611 return Result;
612 }
613 if (dc->IsIC)
614 {
615 DC_UnlockDc(dc);
616 return Result;
617 }
618 XPos += dc->w.DCOrgX;
619 YPos += dc->w.DCOrgY;
620 if ( IN_RECT(dc->CombinedClip->rclBounds,XPos,YPos) )
621 {
622 bInRect = TRUE;
623 BitmapObject = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
624 SurfaceObject = &BitmapObject->SurfObj;
625 if ( BitmapObject )
626 {
627 if ( dc->w.hPalette != 0 )
628 Pal = dc->w.hPalette;
629 /* FIXME: Verify if it shouldn't be PAL_BGR! */
630 XlateObj = (XLATEOBJ*)IntEngCreateXlate ( PAL_RGB, 0, NULL, Pal );
631 if ( XlateObj )
632 {
633 // check if this DC has a DIB behind it...
634 if ( SurfaceObject->pvScan0 ) // STYPE_BITMAP == SurfaceObject->iType
635 {
636 ASSERT ( SurfaceObject->lDelta );
637 Result = XLATEOBJ_iXlate(XlateObj,
638 DibFunctionsForBitmapFormat[SurfaceObject->iBitmapFormat].DIB_GetPixel ( SurfaceObject, XPos, YPos ) );
639 }
640 EngDeleteXlate(XlateObj);
641 }
642 BITMAPOBJ_UnlockBitmap(BitmapObject);
643 }
644 }
645 DC_UnlockDc(dc);
646
647 // if Result is still CLR_INVALID, then the "quick" method above didn't work
648 if ( bInRect && Result == CLR_INVALID )
649 {
650 // FIXME: create a 1x1 32BPP DIB, and blit to it
651 HDC hDCTmp = NtGdiCreateCompatibleDC(hDC);
652 if ( hDCTmp )
653 {
654 static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
655 BITMAPINFO bi;
656 RtlMoveMemory ( &(bi.bmiHeader), &bih, sizeof(bih) );
657 hBmpTmp = NtGdiCreateDIBitmap ( hDC, &bi.bmiHeader, 0, NULL, &bi, DIB_RGB_COLORS );
658 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
659 if ( hBmpTmp )
660 {
661 HBITMAP hBmpOld = (HBITMAP)NtGdiSelectObject ( hDCTmp, hBmpTmp );
662 if ( hBmpOld )
663 {
664 PBITMAPOBJ bmpobj;
665
666 NtGdiBitBlt ( hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0 );
667 NtGdiSelectObject ( hDCTmp, hBmpOld );
668
669 // our bitmap is no longer selected, so we can access it's stuff...
670 bmpobj = BITMAPOBJ_LockBitmap ( hBmpTmp );
671 if ( bmpobj )
672 {
673 Result = *(COLORREF*)bmpobj->SurfObj.pvScan0;
674 BITMAPOBJ_UnlockBitmap ( bmpobj );
675 }
676 }
677 NtGdiDeleteObject ( hBmpTmp );
678 }
679 NtGdiDeleteObjectApp ( hDCTmp );
680 }
681 }
682
683 return Result;
684 }
685
686 /***********************************************************************
687 * MaskBlt
688 * Ported from WINE by sedwards 11-4-03
689 *
690 * Someone thought it would be faster to do it here and then switch back
691 * to GDI32. I dunno. Write a test and let me know.
692 */
693
694 static __inline BYTE
695 SwapROP3_SrcDst(BYTE bRop3)
696 {
697 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
698 }
699
700 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
701 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
702 #define DSTCOPY 0x00AA0029
703 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
704
705 BOOL STDCALL
706 NtGdiMaskBlt (
707 HDC hdcDest, INT nXDest, INT nYDest,
708 INT nWidth, INT nHeight, HDC hdcSrc,
709 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
710 INT xMask, INT yMask, DWORD dwRop,
711 IN DWORD crBackColor)
712 {
713 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
714 HDC hDCMask, hDC1, hDC2;
715 static const DWORD ROP3Table[256] =
716 {
717 0x00000042, 0x00010289,
718 0x00020C89, 0x000300AA,
719 0x00040C88, 0x000500A9,
720 0x00060865, 0x000702C5,
721 0x00080F08, 0x00090245,
722 0x000A0329, 0x000B0B2A,
723 0x000C0324, 0x000D0B25,
724 0x000E08A5, 0x000F0001,
725 0x00100C85, 0x001100A6,
726 0x00120868, 0x001302C8,
727 0x00140869, 0x001502C9,
728 0x00165CCA, 0x00171D54,
729 0x00180D59, 0x00191CC8,
730 0x001A06C5, 0x001B0768,
731 0x001C06CA, 0x001D0766,
732 0x001E01A5, 0x001F0385,
733 0x00200F09, 0x00210248,
734 0x00220326, 0x00230B24,
735 0x00240D55, 0x00251CC5,
736 0x002606C8, 0x00271868,
737 0x00280369, 0x002916CA,
738 0x002A0CC9, 0x002B1D58,
739 0x002C0784, 0x002D060A,
740 0x002E064A, 0x002F0E2A,
741 0x0030032A, 0x00310B28,
742 0x00320688, 0x00330008,
743 0x003406C4, 0x00351864,
744 0x003601A8, 0x00370388,
745 0x0038078A, 0x00390604,
746 0x003A0644, 0x003B0E24,
747 0x003C004A, 0x003D18A4,
748 0x003E1B24, 0x003F00EA,
749 0x00400F0A, 0x00410249,
750 0x00420D5D, 0x00431CC4,
751 0x00440328, 0x00450B29,
752 0x004606C6, 0x0047076A,
753 0x00480368, 0x004916C5,
754 0x004A0789, 0x004B0605,
755 0x004C0CC8, 0x004D1954,
756 0x004E0645, 0x004F0E25,
757 0x00500325, 0x00510B26,
758 0x005206C9, 0x00530764,
759 0x005408A9, 0x00550009,
760 0x005601A9, 0x00570389,
761 0x00580785, 0x00590609,
762 0x005A0049, 0x005B18A9,
763 0x005C0649, 0x005D0E29,
764 0x005E1B29, 0x005F00E9,
765 0x00600365, 0x006116C6,
766 0x00620786, 0x00630608,
767 0x00640788, 0x00650606,
768 0x00660046, 0x006718A8,
769 0x006858A6, 0x00690145,
770 0x006A01E9, 0x006B178A,
771 0x006C01E8, 0x006D1785,
772 0x006E1E28, 0x006F0C65,
773 0x00700CC5, 0x00711D5C,
774 0x00720648, 0x00730E28,
775 0x00740646, 0x00750E26,
776 0x00761B28, 0x007700E6,
777 0x007801E5, 0x00791786,
778 0x007A1E29, 0x007B0C68,
779 0x007C1E24, 0x007D0C69,
780 0x007E0955, 0x007F03C9,
781 0x008003E9, 0x00810975,
782 0x00820C49, 0x00831E04,
783 0x00840C48, 0x00851E05,
784 0x008617A6, 0x008701C5,
785 0x008800C6, 0x00891B08,
786 0x008A0E06, 0x008B0666,
787 0x008C0E08, 0x008D0668,
788 0x008E1D7C, 0x008F0CE5,
789 0x00900C45, 0x00911E08,
790 0x009217A9, 0x009301C4,
791 0x009417AA, 0x009501C9,
792 0x00960169, 0x0097588A,
793 0x00981888, 0x00990066,
794 0x009A0709, 0x009B07A8,
795 0x009C0704, 0x009D07A6,
796 0x009E16E6, 0x009F0345,
797 0x00A000C9, 0x00A11B05,
798 0x00A20E09, 0x00A30669,
799 0x00A41885, 0x00A50065,
800 0x00A60706, 0x00A707A5,
801 0x00A803A9, 0x00A90189,
802 0x00AA0029, 0x00AB0889,
803 0x00AC0744, 0x00AD06E9,
804 0x00AE0B06, 0x00AF0229,
805 0x00B00E05, 0x00B10665,
806 0x00B21974, 0x00B30CE8,
807 0x00B4070A, 0x00B507A9,
808 0x00B616E9, 0x00B70348,
809 0x00B8074A, 0x00B906E6,
810 0x00BA0B09, 0x00BB0226,
811 0x00BC1CE4, 0x00BD0D7D,
812 0x00BE0269, 0x00BF08C9,
813 0x00C000CA, 0x00C11B04,
814 0x00C21884, 0x00C3006A,
815 0x00C40E04, 0x00C50664,
816 0x00C60708, 0x00C707AA,
817 0x00C803A8, 0x00C90184,
818 0x00CA0749, 0x00CB06E4,
819 0x00CC0020, 0x00CD0888,
820 0x00CE0B08, 0x00CF0224,
821 0x00D00E0A, 0x00D1066A,
822 0x00D20705, 0x00D307A4,
823 0x00D41D78, 0x00D50CE9,
824 0x00D616EA, 0x00D70349,
825 0x00D80745, 0x00D906E8,
826 0x00DA1CE9, 0x00DB0D75,
827 0x00DC0B04, 0x00DD0228,
828 0x00DE0268, 0x00DF08C8,
829 0x00E003A5, 0x00E10185,
830 0x00E20746, 0x00E306EA,
831 0x00E40748, 0x00E506E5,
832 0x00E61CE8, 0x00E70D79,
833 0x00E81D74, 0x00E95CE6,
834 0x00EA02E9, 0x00EB0849,
835 0x00EC02E8, 0x00ED0848,
836 0x00EE0086, 0x00EF0A08,
837 0x00F00021, 0x00F10885,
838 0x00F20B05, 0x00F3022A,
839 0x00F40B0A, 0x00F50225,
840 0x00F60265, 0x00F708C5,
841 0x00F802E5, 0x00F90845,
842 0x00FA0089, 0x00FB0A09,
843 0x00FC008A, 0x00FD0A0A,
844 0x00FE02A9, 0x00FF0062,
845 };
846
847 if (!hbmMask)
848 return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0, 0);
849
850 /* 1. make mask bitmap's dc */
851 hDCMask = NtGdiCreateCompatibleDC(hdcDest);
852 hOldMaskBitmap = (HBITMAP)NtGdiSelectObject(hDCMask, hbmMask);
853
854 /* 2. make masked Background bitmap */
855
856 /* 2.1 make bitmap */
857 hDC1 = NtGdiCreateCompatibleDC(hdcDest);
858 hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
859 hOldBitmap2 = (HBITMAP)NtGdiSelectObject(hDC1, hBitmap2);
860
861 /* 2.2 draw dest bitmap and mask */
862 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0);
863 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0);
864 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE, 0, 0);
865
866 /* 3. make masked Foreground bitmap */
867
868 /* 3.1 make bitmap */
869 hDC2 = NtGdiCreateCompatibleDC(hdcDest);
870 hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
871 hOldBitmap3 = (HBITMAP)NtGdiSelectObject(hDC2, hBitmap3);
872
873 /* 3.2 draw src bitmap and mask */
874 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0);
875 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0);
876 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND, 0, 0);
877
878 /* 4. combine two bitmap and copy it to hdcDest */
879 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT, 0, 0);
880 NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY, 0, 0);
881
882 /* 5. restore all object */
883 NtGdiSelectObject(hDCMask, hOldMaskBitmap);
884 NtGdiSelectObject(hDC1, hOldBitmap2);
885 NtGdiSelectObject(hDC2, hOldBitmap3);
886
887 /* 6. delete all temp object */
888 NtGdiDeleteObject(hBitmap2);
889 NtGdiDeleteObject(hBitmap3);
890
891 NtGdiDeleteObjectApp(hDC1);
892 NtGdiDeleteObjectApp(hDC2);
893 NtGdiDeleteObjectApp(hDCMask);
894
895 return TRUE;
896 }
897
898 BOOL
899 APIENTRY
900 NtGdiPlgBlt(
901 IN HDC hdcTrg,
902 IN LPPOINT pptlTrg,
903 IN HDC hdcSrc,
904 IN INT xSrc,
905 IN INT ySrc,
906 IN INT cxSrc,
907 IN INT cySrc,
908 IN HBITMAP hbmMask,
909 IN INT xMask,
910 IN INT yMask,
911 IN DWORD crBackColor)
912 {
913 UNIMPLEMENTED;
914 return FALSE;
915 }
916
917
918 LONG STDCALL
919 IntGetBitmapBits(
920 PBITMAPOBJ bmp,
921 DWORD Bytes,
922 OUT PBYTE Bits)
923 {
924 LONG ret;
925
926 ASSERT(Bits);
927
928 /* Don't copy more bytes than the buffer has */
929 Bytes = min(Bytes, bmp->SurfObj.cjBits);
930
931 #if 0
932 /* FIXME: Call DDI CopyBits here if available */
933 if(bmp->DDBitmap)
934 {
935 DPRINT("Calling device specific BitmapBits\n");
936 if(bmp->DDBitmap->funcs->pBitmapBits)
937 {
938 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count, DDB_GET);
939 }
940 else
941 {
942 ERR_(bitmap)("BitmapBits == NULL??\n");
943 ret = 0;
944 }
945 }
946 else
947 #endif
948 {
949 RtlCopyMemory(Bits, bmp->SurfObj.pvBits, Bytes);
950 ret = Bytes;
951 }
952 return ret;
953 }
954
955 LONG STDCALL
956 NtGdiGetBitmapBits(HBITMAP hBitmap,
957 ULONG Bytes,
958 OUT OPTIONAL PBYTE pUnsafeBits)
959 {
960 PBITMAPOBJ bmp;
961 LONG ret;
962
963 if (pUnsafeBits != NULL && Bytes == 0)
964 {
965 return 0;
966 }
967
968 bmp = BITMAPOBJ_LockBitmap (hBitmap);
969 if (!bmp)
970 {
971 SetLastWin32Error(ERROR_INVALID_HANDLE);
972 return 0;
973 }
974
975 /* If the bits vector is null, the function should return the read size */
976 if (pUnsafeBits == NULL)
977 {
978 ret = bmp->SurfObj.cjBits;
979 BITMAPOBJ_UnlockBitmap (bmp);
980 return ret;
981 }
982
983 /* Don't copy more bytes than the buffer has */
984 Bytes = min(Bytes, bmp->SurfObj.cjBits);
985
986 _SEH_TRY
987 {
988 ProbeForWrite(pUnsafeBits, Bytes, 1);
989 ret = IntGetBitmapBits(bmp, Bytes, pUnsafeBits);
990 }
991 _SEH_HANDLE
992 {
993 ret = 0;
994 }
995 _SEH_END
996
997 BITMAPOBJ_UnlockBitmap (bmp);
998
999 return ret;
1000 }
1001
1002
1003 LONG STDCALL
1004 IntSetBitmapBits(
1005 PBITMAPOBJ bmp,
1006 DWORD Bytes,
1007 IN PBYTE Bits)
1008 {
1009 LONG ret;
1010
1011 /* Don't copy more bytes than the buffer has */
1012 Bytes = min(Bytes, bmp->SurfObj.cjBits);
1013
1014 #if 0
1015 /* FIXME: call DDI specific function here if available */
1016 if(bmp->DDBitmap)
1017 {
1018 DPRINT ("Calling device specific BitmapBits\n");
1019 if (bmp->DDBitmap->funcs->pBitmapBits)
1020 {
1021 ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET);
1022 }
1023 else
1024 {
1025 DPRINT ("BitmapBits == NULL??\n");
1026 ret = 0;
1027 }
1028 }
1029 else
1030 #endif
1031 {
1032 RtlCopyMemory(bmp->SurfObj.pvBits, Bits, Bytes);
1033 ret = Bytes;
1034 }
1035
1036 return ret;
1037 }
1038
1039
1040 LONG STDCALL
1041 NtGdiSetBitmapBits(
1042 HBITMAP hBitmap,
1043 DWORD Bytes,
1044 IN PBYTE pUnsafeBits)
1045 {
1046 LONG ret;
1047 PBITMAPOBJ bmp;
1048
1049 if (pUnsafeBits == NULL || Bytes == 0)
1050 {
1051 return 0;
1052 }
1053
1054 bmp = BITMAPOBJ_LockBitmap(hBitmap);
1055 if (bmp == NULL)
1056 {
1057 SetLastWin32Error(ERROR_INVALID_HANDLE);
1058 return 0;
1059 }
1060
1061 _SEH_TRY
1062 {
1063 ProbeForRead(pUnsafeBits, Bytes, 1);
1064 ret = IntSetBitmapBits(bmp, Bytes, pUnsafeBits);
1065 }
1066 _SEH_HANDLE
1067 {
1068 ret = 0;
1069 }
1070 _SEH_END
1071
1072 BITMAPOBJ_UnlockBitmap(bmp);
1073
1074 return ret;
1075 }
1076
1077 BOOL STDCALL
1078 NtGdiSetBitmapDimension(
1079 HBITMAP hBitmap,
1080 INT Width,
1081 INT Height,
1082 LPSIZE Size)
1083 {
1084 PBITMAPOBJ bmp;
1085
1086 bmp = BITMAPOBJ_LockBitmap(hBitmap);
1087 if (bmp == NULL)
1088 {
1089 return FALSE;
1090 }
1091
1092 if (Size)
1093 {
1094 *Size = bmp->dimension;
1095 }
1096 bmp->dimension.cx = Width;
1097 bmp->dimension.cy = Height;
1098
1099 BITMAPOBJ_UnlockBitmap (bmp);
1100
1101 return TRUE;
1102 }
1103
1104 COLORREF STDCALL
1105 NtGdiSetPixel(
1106 HDC hDC,
1107 INT X,
1108 INT Y,
1109 COLORREF Color)
1110 {
1111
1112 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1113
1114
1115 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1116
1117 if (NtGdiSetPixelV(hDC,X,Y,Color))
1118 {
1119 Color = NtGdiGetPixel(hDC,X,Y);
1120 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1121 return Color;
1122 }
1123
1124 Color = ((COLORREF) -1);
1125 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
1126 return Color;
1127 }
1128
1129 BOOL STDCALL
1130 NtGdiSetPixelV(
1131 HDC hDC,
1132 INT X,
1133 INT Y,
1134 COLORREF Color)
1135 {
1136 HBRUSH NewBrush = NtGdiCreateSolidBrush(Color, NULL);
1137 HGDIOBJ OldBrush;
1138
1139 if (NewBrush == NULL)
1140 return(FALSE);
1141 OldBrush = NtGdiSelectObject(hDC, NewBrush);
1142 if (OldBrush == NULL)
1143 {
1144 NtGdiDeleteObject(NewBrush);
1145 return(FALSE);
1146 }
1147 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
1148 NtGdiSelectObject(hDC, OldBrush);
1149 NtGdiDeleteObject(NewBrush);
1150 return TRUE;
1151 }
1152
1153 BOOL STDCALL
1154 NtGdiStretchBlt(
1155 HDC hDCDest,
1156 INT XOriginDest,
1157 INT YOriginDest,
1158 INT WidthDest,
1159 INT HeightDest,
1160 HDC hDCSrc,
1161 INT XOriginSrc,
1162 INT YOriginSrc,
1163 INT WidthSrc,
1164 INT HeightSrc,
1165 DWORD ROP,
1166 IN DWORD dwBackColor)
1167 {
1168 PDC DCDest = NULL;
1169 PDC DCSrc = NULL;
1170 BITMAPOBJ *BitmapDest, *BitmapSrc;
1171 RECTL DestRect;
1172 RECTL SourceRect;
1173 BOOL Status;
1174 XLATEOBJ *XlateObj = NULL;
1175 HPALETTE SourcePalette = 0, DestPalette = 0;
1176 PGDIBRUSHOBJ BrushObj;
1177 BOOL UsesSource = ((ROP & 0xCC0000) >> 2) != (ROP & 0x330000);
1178 BOOL UsesPattern = ((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
1179
1180 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
1181 {
1182 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1183 return FALSE;
1184 }
1185 DCDest = DC_LockDc(hDCDest);
1186 if (NULL == DCDest)
1187 {
1188 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
1189 SetLastWin32Error(ERROR_INVALID_HANDLE);
1190 return FALSE;
1191 }
1192 if (DCDest->IsIC)
1193 {
1194 DC_UnlockDc(DCDest);
1195 /* Yes, Windows really returns TRUE in this case */
1196 return TRUE;
1197 }
1198
1199 if (UsesSource)
1200 {
1201 if (hDCSrc != hDCDest)
1202 {
1203 DCSrc = DC_LockDc(hDCSrc);
1204 if (NULL == DCSrc)
1205 {
1206 DC_UnlockDc(DCDest);
1207 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
1208 SetLastWin32Error(ERROR_INVALID_HANDLE);
1209 return FALSE;
1210 }
1211 if (DCSrc->IsIC)
1212 {
1213 DC_UnlockDc(DCSrc);
1214 DC_UnlockDc(DCDest);
1215 /* Yes, Windows really returns TRUE in this case */
1216 return TRUE;
1217 }
1218 }
1219 else
1220 {
1221 DCSrc = DCDest;
1222 }
1223 }
1224 else
1225 {
1226 DCSrc = NULL;
1227 }
1228
1229 /* Offset the destination and source by the origin of their DCs. */
1230 XOriginDest += DCDest->w.DCOrgX;
1231 YOriginDest += DCDest->w.DCOrgY;
1232 if (UsesSource)
1233 {
1234 XOriginSrc += DCSrc->w.DCOrgX;
1235 YOriginSrc += DCSrc->w.DCOrgY;
1236 }
1237
1238 DestRect.left = XOriginDest;
1239 DestRect.top = YOriginDest;
1240 DestRect.right = XOriginDest+WidthDest;
1241 DestRect.bottom = YOriginDest+HeightDest;
1242
1243 SourceRect.left = XOriginSrc;
1244 SourceRect.top = YOriginSrc;
1245 SourceRect.right = XOriginSrc+WidthSrc;
1246 SourceRect.bottom = YOriginSrc+HeightSrc;
1247
1248 /* Determine surfaces to be used in the bitblt */
1249 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
1250 if (UsesSource)
1251 {
1252 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
1253 BitmapSrc = BitmapDest;
1254 else
1255 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
1256 }
1257 else
1258 {
1259 BitmapSrc = NULL;
1260 }
1261
1262 if ( UsesSource )
1263 {
1264 int sw = BitmapSrc->SurfObj.sizlBitmap.cx;
1265 int sh = BitmapSrc->SurfObj.sizlBitmap.cy;
1266 if ( SourceRect.left < 0 )
1267 {
1268 DestRect.left = DestRect.right - (DestRect.right-DestRect.left) * (SourceRect.right)/abs(SourceRect.right-SourceRect.left);
1269 SourceRect.left = 0;
1270 }
1271 if ( SourceRect.top < 0 )
1272 {
1273 DestRect.top = DestRect.bottom - (DestRect.bottom-DestRect.top) * (SourceRect.bottom)/abs(SourceRect.bottom-SourceRect.top);
1274 SourceRect.top = 0;
1275 }
1276 if ( SourceRect.right < -1 )
1277 {
1278 DestRect.right = DestRect.left + (DestRect.right-DestRect.left) * (-1-SourceRect.left)/abs(SourceRect.right-SourceRect.left);
1279 SourceRect.right = -1;
1280 }
1281 if ( SourceRect.bottom < -1 )
1282 {
1283 DestRect.bottom = DestRect.top + (DestRect.bottom-DestRect.top) * (-1-SourceRect.top)/abs(SourceRect.bottom-SourceRect.top);
1284 SourceRect.bottom = -1;
1285 }
1286 if ( SourceRect.right > sw )
1287 {
1288 DestRect.right = DestRect.left + (DestRect.right-DestRect.left) * abs(sw-SourceRect.left) / abs(SourceRect.right-SourceRect.left);
1289 SourceRect.right = sw;
1290 }
1291 if ( SourceRect.bottom > sh )
1292 {
1293 DestRect.bottom = DestRect.top + (DestRect.bottom-DestRect.top) * abs(sh-SourceRect.top) / abs(SourceRect.bottom-SourceRect.top);
1294 SourceRect.bottom = sh;
1295 }
1296 sw--;
1297 sh--;
1298 if ( SourceRect.left > sw )
1299 {
1300 DestRect.left = DestRect.right - (DestRect.right-DestRect.left) * (SourceRect.right-sw) / abs(SourceRect.right-SourceRect.left);
1301 SourceRect.left = 0;
1302 }
1303 if ( SourceRect.top > sh )
1304 {
1305 DestRect.top = DestRect.bottom - (DestRect.bottom-DestRect.top) * (SourceRect.bottom-sh) / abs(SourceRect.bottom-SourceRect.top);
1306 SourceRect.top = 0;
1307 }
1308 if (0 == (DestRect.right-DestRect.left) || 0 == (DestRect.bottom-DestRect.top) || 0 == (SourceRect.right-SourceRect.left) || 0 == (SourceRect.bottom-SourceRect.top))
1309 {
1310 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1311 Status = FALSE;
1312 goto failed;
1313 }
1314 }
1315
1316 if (UsesPattern)
1317 {
1318 BrushObj = BRUSHOBJ_LockBrush(DCDest->Dc_Attr.hbrush);
1319 if (NULL == BrushObj)
1320 {
1321 if (UsesSource && hDCSrc != hDCDest)
1322 {
1323 DC_UnlockDc(DCSrc);
1324 }
1325 DC_UnlockDc(DCDest);
1326 SetLastWin32Error(ERROR_INVALID_HANDLE);
1327 return FALSE;
1328 }
1329 }
1330 else
1331 {
1332 BrushObj = NULL;
1333 }
1334
1335 /* Create the XLATEOBJ. */
1336 if (UsesSource)
1337 {
1338 if (DCDest->w.hPalette != 0)
1339 DestPalette = DCDest->w.hPalette;
1340
1341 if (DCSrc->w.hPalette != 0)
1342 SourcePalette = DCSrc->w.hPalette;
1343
1344 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1345 XlateObj = (XLATEOBJ*)IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
1346 if (NULL == XlateObj)
1347 {
1348 if (UsesSource && hDCSrc != hDCDest)
1349 {
1350 DC_UnlockDc(DCSrc);
1351 }
1352 DC_UnlockDc(DCDest);
1353 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1354 return FALSE;
1355 }
1356 }
1357
1358 /* Perform the bitblt operation */
1359 Status = IntEngStretchBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
1360 NULL, DCDest->CombinedClip, XlateObj,
1361 &DestRect, &SourceRect, NULL, NULL, NULL,
1362 COLORONCOLOR);
1363
1364 if (UsesSource)
1365 EngDeleteXlate(XlateObj);
1366 if (UsesPattern)
1367 {
1368 BRUSHOBJ_UnlockBrush(BrushObj);
1369 }
1370 failed:
1371 if (UsesSource && DCSrc->w.hBitmap != DCDest->w.hBitmap)
1372 {
1373 BITMAPOBJ_UnlockBitmap(BitmapSrc);
1374 }
1375 BITMAPOBJ_UnlockBitmap(BitmapDest);
1376 if (UsesSource && hDCSrc != hDCDest)
1377 {
1378 DC_UnlockDc(DCSrc);
1379 }
1380 DC_UnlockDc(DCDest);
1381
1382 return Status;
1383 }
1384
1385 BOOL STDCALL
1386 NtGdiAlphaBlend(
1387 HDC hDCDest,
1388 LONG XOriginDest,
1389 LONG YOriginDest,
1390 LONG WidthDest,
1391 LONG HeightDest,
1392 HDC hDCSrc,
1393 LONG XOriginSrc,
1394 LONG YOriginSrc,
1395 LONG WidthSrc,
1396 LONG HeightSrc,
1397 BLENDFUNCTION BlendFunc,
1398 HANDLE hcmXform)
1399 {
1400 PDC DCDest = NULL;
1401 PDC DCSrc = NULL;
1402 BITMAPOBJ *BitmapDest, *BitmapSrc;
1403 RECTL DestRect, SourceRect;
1404 BOOL Status;
1405 XLATEOBJ *XlateObj;
1406 BLENDOBJ BlendObj;
1407 HPALETTE SourcePalette = 0, DestPalette = 0;
1408 BlendObj.BlendFunction = BlendFunc;
1409
1410 DCDest = DC_LockDc(hDCDest);
1411 if (NULL == DCDest)
1412 {
1413 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest);
1414 SetLastWin32Error(ERROR_INVALID_HANDLE);
1415 return FALSE;
1416 }
1417 if (DCDest->IsIC)
1418 {
1419 DC_UnlockDc(DCDest);
1420 /* Yes, Windows really returns TRUE in this case */
1421 return TRUE;
1422 }
1423
1424 if (hDCSrc != hDCDest)
1425 {
1426 DCSrc = DC_LockDc(hDCSrc);
1427 if (NULL == DCSrc)
1428 {
1429 DC_UnlockDc(DCDest);
1430 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc);
1431 SetLastWin32Error(ERROR_INVALID_HANDLE);
1432 return FALSE;
1433 }
1434 if (DCSrc->IsIC)
1435 {
1436 DC_UnlockDc(DCSrc);
1437 DC_UnlockDc(DCDest);
1438 /* Yes, Windows really returns TRUE in this case */
1439 return TRUE;
1440 }
1441 }
1442 else
1443 {
1444 DCSrc = DCDest;
1445 }
1446
1447 /* Offset the destination and source by the origin of their DCs. */
1448 XOriginDest += DCDest->w.DCOrgX;
1449 YOriginDest += DCDest->w.DCOrgY;
1450 XOriginSrc += DCSrc->w.DCOrgX;
1451 YOriginSrc += DCSrc->w.DCOrgY;
1452
1453 DestRect.left = XOriginDest;
1454 DestRect.top = YOriginDest;
1455 DestRect.right = XOriginDest + WidthDest;
1456 DestRect.bottom = YOriginDest + HeightDest;
1457
1458 SourceRect.left = XOriginSrc;
1459 SourceRect.top = YOriginSrc;
1460 SourceRect.right = XOriginSrc + WidthSrc;
1461 SourceRect.bottom = YOriginSrc + HeightSrc;
1462
1463 /* Determine surfaces to be used in the bitblt */
1464 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
1465 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
1466 BitmapSrc = BitmapDest;
1467 else
1468 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
1469
1470 /* Create the XLATEOBJ. */
1471 if (DCDest->w.hPalette != 0)
1472 DestPalette = DCDest->w.hPalette;
1473 if (DCSrc->w.hPalette != 0)
1474 SourcePalette = DCSrc->w.hPalette;
1475
1476 /* KB41464 details how to convert between mono and color */
1477 if (DCDest->w.bitsPerPixel == 1 && DCSrc->w.bitsPerPixel == 1)
1478 {
1479 XlateObj = NULL;
1480 }
1481 else
1482 {
1483 if (DCDest->w.bitsPerPixel == 1)
1484 {
1485 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, DCSrc->Dc_Attr.crBackgroundClr);
1486 }
1487 else if (DCSrc->w.bitsPerPixel == 1)
1488 {
1489 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, DCSrc->Dc_Attr.crBackgroundClr, DCSrc->Dc_Attr.crForegroundClr);
1490 }
1491 else
1492 {
1493 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
1494 }
1495 if (NULL == XlateObj)
1496 {
1497 BITMAPOBJ_UnlockBitmap(BitmapDest);
1498 if (BitmapSrc != BitmapDest)
1499 BITMAPOBJ_UnlockBitmap(BitmapSrc);
1500 DC_UnlockDc(DCDest);
1501 if (hDCSrc != hDCDest)
1502 DC_UnlockDc(DCSrc);
1503 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1504 return FALSE;
1505 }
1506 }
1507
1508 /* Perform the alpha blend operation */
1509 Status = IntEngAlphaBlend(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
1510 DCDest->CombinedClip, XlateObj,
1511 &DestRect, &SourceRect, &BlendObj);
1512
1513 if (XlateObj != NULL)
1514 EngDeleteXlate(XlateObj);
1515
1516 BITMAPOBJ_UnlockBitmap(BitmapDest);
1517 if (BitmapSrc != BitmapDest)
1518 BITMAPOBJ_UnlockBitmap(BitmapSrc);
1519 DC_UnlockDc(DCDest);
1520 if (hDCSrc != hDCDest)
1521 DC_UnlockDc(DCSrc);
1522
1523 return Status;
1524 }
1525
1526 /* Internal Functions */
1527
1528 INT FASTCALL
1529 BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
1530 {
1531 #if 0
1532 switch(bpp)
1533 {
1534 case 1:
1535 return 2 * ((bmWidth+15) >> 4);
1536
1537 case 24:
1538 bmWidth *= 3; /* fall through */
1539 case 8:
1540 return bmWidth + (bmWidth & 1);
1541
1542 case 32:
1543 return bmWidth * 4;
1544
1545 case 16:
1546 case 15:
1547 return bmWidth * 2;
1548
1549 case 4:
1550 return 2 * ((bmWidth+3) >> 2);
1551
1552 default:
1553 DPRINT ("stub");
1554 }
1555
1556 return -1;
1557 #endif
1558
1559 return ((bmWidth * bpp + 15) & ~15) >> 3;
1560 }
1561
1562 HBITMAP FASTCALL
1563 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
1564 {
1565 HBITMAP res;
1566 BITMAP bm;
1567 BITMAPOBJ *Bitmap, *resBitmap;
1568 SIZEL Size;
1569
1570 if (hBitmap == NULL)
1571 {
1572 return 0;
1573 }
1574
1575 Bitmap = GDIOBJ_LockObj(GdiHandleTable, hBitmap, GDI_OBJECT_TYPE_BITMAP);
1576 if (Bitmap == NULL)
1577 {
1578 return 0;
1579 }
1580
1581 BITMAP_GetObject(Bitmap, sizeof(BITMAP), &bm);
1582 bm.bmBits = NULL;
1583 if (Bitmap->SurfObj.lDelta >= 0)
1584 bm.bmHeight = -bm.bmHeight;
1585
1586 Size.cx = abs(bm.bmWidth);
1587 Size.cy = abs(bm.bmHeight);
1588 res = IntCreateBitmap(Size,
1589 bm.bmWidthBytes,
1590 BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
1591 (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
1592 NULL);
1593
1594 if(res)
1595 {
1596 PBYTE buf;
1597
1598 resBitmap = GDIOBJ_LockObj(GdiHandleTable, res, GDI_OBJECT_TYPE_BITMAP);
1599 if (resBitmap)
1600 {
1601 buf = ExAllocatePoolWithTag (PagedPool, bm.bmWidthBytes * abs(bm.bmHeight), TAG_BITMAP);
1602 IntGetBitmapBits (Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
1603 IntSetBitmapBits (resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
1604 ExFreePool (buf);
1605 GDIOBJ_UnlockObjByPtr(GdiHandleTable, resBitmap);
1606 }
1607 }
1608
1609 GDIOBJ_UnlockObjByPtr(GdiHandleTable, Bitmap);
1610
1611 return res;
1612 }
1613
1614 INT STDCALL
1615 BITMAP_GetObject(BITMAPOBJ * bmp, INT Count, LPVOID buffer)
1616 {
1617 if ((UINT)Count < sizeof(BITMAP)) return 0;
1618
1619 if(bmp->dib)
1620 {
1621 if((UINT)Count < sizeof(DIBSECTION))
1622 {
1623 Count = sizeof(BITMAP);
1624 }
1625 else
1626 {
1627 Count = sizeof(DIBSECTION);
1628 }
1629 if (buffer)
1630 {
1631 memcpy(buffer, bmp->dib, Count);
1632 }
1633 return Count;
1634 }
1635 else
1636 {
1637 Count = sizeof(BITMAP);
1638 if (buffer)
1639 {
1640 BITMAP Bitmap;
1641
1642 Count = sizeof(BITMAP);
1643 Bitmap.bmType = 0;
1644 Bitmap.bmWidth = bmp->SurfObj.sizlBitmap.cx;
1645 Bitmap.bmHeight = bmp->SurfObj.sizlBitmap.cy;
1646 Bitmap.bmWidthBytes = abs(bmp->SurfObj.lDelta);
1647 Bitmap.bmPlanes = 1;
1648 Bitmap.bmBitsPixel = BitsPerFormat(bmp->SurfObj.iBitmapFormat);
1649 //Bitmap.bmBits = bmp->SurfObj.pvBits;
1650 Bitmap.bmBits = NULL; /* not set accoring wine test confirm in win2k */
1651 memcpy(buffer, &Bitmap, Count);
1652 }
1653 return Count;
1654 }
1655 }
1656 /* EOF */