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