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