Sync with trunk (r48042), except win32k/ntuser/cursoricon.c
[reactos.git] / subsystems / win32 / win32k / objects / bitblt.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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* $Id: bitmaps.c 28300 2007-08-12 15:20:09Z tkreuzer $ */
20
21 #include <win32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26
27
28 BOOL APIENTRY
29 NtGdiAlphaBlend(
30 HDC hDCDest,
31 LONG XOriginDest,
32 LONG YOriginDest,
33 LONG WidthDest,
34 LONG HeightDest,
35 HDC hDCSrc,
36 LONG XOriginSrc,
37 LONG YOriginSrc,
38 LONG WidthSrc,
39 LONG HeightSrc,
40 BLENDFUNCTION BlendFunc,
41 HANDLE hcmXform)
42 {
43 PDC DCDest;
44 PDC DCSrc;
45 HDC ahDC[2];
46 PGDIOBJ apObj[2];
47 SURFACE *BitmapDest, *BitmapSrc;
48 RECTL DestRect, SourceRect;
49 BOOL bResult;
50 EXLATEOBJ exlo;
51 BLENDOBJ BlendObj;
52 BlendObj.BlendFunction = BlendFunc;
53
54 if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0)
55 {
56 SetLastWin32Error(ERROR_INVALID_PARAMETER);
57 return FALSE;
58 }
59
60 DPRINT("Locking DCs\n");
61 ahDC[0] = hDCDest;
62 ahDC[1] = hDCSrc ;
63 GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
64 DCDest = apObj[0];
65 DCSrc = apObj[1];
66
67 if ((NULL == DCDest) || (NULL == DCSrc))
68 {
69 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
70 SetLastWin32Error(ERROR_INVALID_HANDLE);
71 if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
72 if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
73 return FALSE;
74 }
75
76 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
77 {
78 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
79 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
80 /* Yes, Windows really returns TRUE in this case */
81 return TRUE;
82 }
83
84 DestRect.left = XOriginDest;
85 DestRect.top = YOriginDest;
86 DestRect.right = XOriginDest + WidthDest;
87 DestRect.bottom = YOriginDest + HeightDest;
88 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
89
90 DestRect.left += DCDest->ptlDCOrig.x;
91 DestRect.top += DCDest->ptlDCOrig.y;
92 DestRect.right += DCDest->ptlDCOrig.x;
93 DestRect.bottom += DCDest->ptlDCOrig.y;
94
95 SourceRect.left = XOriginSrc;
96 SourceRect.top = YOriginSrc;
97 SourceRect.right = XOriginSrc + WidthSrc;
98 SourceRect.bottom = YOriginSrc + HeightSrc;
99 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
100
101 SourceRect.left += DCSrc->ptlDCOrig.x;
102 SourceRect.top += DCSrc->ptlDCOrig.y;
103 SourceRect.right += DCSrc->ptlDCOrig.x;
104 SourceRect.bottom += DCSrc->ptlDCOrig.y;
105
106 if (!DestRect.right ||
107 !DestRect.bottom ||
108 !SourceRect.right ||
109 !SourceRect.bottom)
110 {
111 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
112 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
113 return TRUE;
114 }
115
116 /* Prepare DCs for blit */
117 DPRINT("Preparing DCs for blit\n");
118 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
119
120 /* Determine surfaces to be used in the bitblt */
121 BitmapDest = DCDest->dclevel.pSurface;
122 if (!BitmapDest)
123 {
124 bResult = FALSE ;
125 goto leave ;
126 }
127
128 BitmapSrc = DCSrc->dclevel.pSurface;
129 if (!BitmapSrc)
130 {
131 bResult = FALSE;
132 goto leave;
133 }
134
135 /* Create the XLATEOBJ. */
136 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
137
138 /* Perform the alpha blend operation */
139 DPRINT("Performing the alpha Blend\n");
140 bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
141 &BitmapSrc->SurfObj,
142 DCDest->rosdc.CombinedClip,
143 &exlo.xlo,
144 &DestRect,
145 &SourceRect,
146 &BlendObj);
147
148 EXLATEOBJ_vCleanup(&exlo);
149 leave :
150 DPRINT("Finishing blit\n");
151 DC_vFinishBlit(DCDest, DCSrc);
152 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
153 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
154
155 return bResult;
156 }
157
158 BOOL APIENTRY
159 NtGdiBitBlt(
160 HDC hDCDest,
161 INT XDest,
162 INT YDest,
163 INT Width,
164 INT Height,
165 HDC hDCSrc,
166 INT XSrc,
167 INT YSrc,
168 DWORD ROP,
169 IN DWORD crBackColor,
170 IN FLONG fl)
171 {
172 PDC DCDest;
173 PDC DCSrc = NULL;
174 HDC ahDC[2];
175 PGDIOBJ apObj[2];
176 PDC_ATTR pdcattr = NULL;
177 SURFACE *BitmapDest, *BitmapSrc = NULL;
178 RECTL DestRect, SourceRect;
179 POINTL SourcePoint;
180 BOOL Status = FALSE;
181 EXLATEOBJ exlo;
182 XLATEOBJ *XlateObj = NULL;
183 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
184
185 DPRINT("Locking DCs\n");
186 ahDC[0] = hDCDest;
187 ahDC[1] = hDCSrc ;
188 GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
189 DCDest = apObj[0];
190 DCSrc = apObj[1];
191
192 if (NULL == DCDest)
193 {
194 if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
195 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
196 return FALSE;
197 }
198
199 if (DCDest->dctype == DC_TYPE_INFO)
200 {
201 if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
202 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
203 /* Yes, Windows really returns TRUE in this case */
204 return TRUE;
205 }
206
207 if (UsesSource)
208 {
209 if (NULL == DCSrc)
210 {
211 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
212 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
213 return FALSE;
214 }
215 if (DCSrc->dctype == DC_TYPE_INFO)
216 {
217 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
218 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
219 /* Yes, Windows really returns TRUE in this case */
220 return TRUE;
221 }
222 }
223 else if(DCSrc)
224 {
225 DPRINT1("Getting a valid Source handle without using source!!!\n");
226 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
227 DCSrc = NULL ;
228 }
229
230 pdcattr = DCDest->pdcattr;
231
232 DestRect.left = XDest;
233 DestRect.top = YDest;
234 DestRect.right = XDest+Width;
235 DestRect.bottom = YDest+Height;
236 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
237
238 DestRect.left += DCDest->ptlDCOrig.x;
239 DestRect.top += DCDest->ptlDCOrig.y;
240 DestRect.right += DCDest->ptlDCOrig.x;
241 DestRect.bottom += DCDest->ptlDCOrig.y;
242
243 SourcePoint.x = XSrc;
244 SourcePoint.y = YSrc;
245
246 if (UsesSource)
247 {
248 IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);
249
250 SourcePoint.x += DCSrc->ptlDCOrig.x;
251 SourcePoint.y += DCSrc->ptlDCOrig.y;
252 /* Calculate Source Rect */
253 SourceRect.left = SourcePoint.x;
254 SourceRect.top = SourcePoint.y;
255 SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
256 SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
257 }
258
259 /* Prepare blit */
260 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
261
262 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
263 DC_vUpdateFillBrush(DCDest);
264
265 /* Determine surfaces to be used in the bitblt */
266 BitmapDest = DCDest->dclevel.pSurface;
267 if (!BitmapDest)
268 goto cleanup;
269
270 if (UsesSource)
271 {
272 {
273 BitmapSrc = DCSrc->dclevel.pSurface;
274 if (!BitmapSrc)
275 goto cleanup;
276 }
277 }
278
279 /* Create the XLATEOBJ. */
280 if (UsesSource)
281 {
282 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
283 XlateObj = &exlo.xlo;
284 }
285
286 /* Perform the bitblt operation */
287 Status = IntEngBitBlt(&BitmapDest->SurfObj,
288 BitmapSrc ? &BitmapSrc->SurfObj : NULL,
289 NULL,
290 DCDest->rosdc.CombinedClip,
291 XlateObj,
292 &DestRect,
293 &SourcePoint,
294 NULL,
295 &DCDest->eboFill.BrushObject,
296 &DCDest->dclevel.pbrFill->ptOrigin,
297 ROP3_TO_ROP4(ROP));
298
299 if (UsesSource)
300 EXLATEOBJ_vCleanup(&exlo);
301 cleanup:
302 DC_vFinishBlit(DCDest, DCSrc);
303 if (UsesSource)
304 {
305 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
306 }
307 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
308
309 return Status;
310 }
311
312 BOOL APIENTRY
313 NtGdiTransparentBlt(
314 HDC hdcDst,
315 INT xDst,
316 INT yDst,
317 INT cxDst,
318 INT cyDst,
319 HDC hdcSrc,
320 INT xSrc,
321 INT ySrc,
322 INT cxSrc,
323 INT cySrc,
324 COLORREF TransColor)
325 {
326 PDC DCDest, DCSrc;
327 HDC ahDC[2];
328 PGDIOBJ apObj[2];
329 RECTL rcDest, rcSrc;
330 SURFACE *BitmapDest, *BitmapSrc = NULL;
331 PPALETTE PalSourceGDI;
332 ULONG TransparentColor = 0;
333 BOOL Ret = FALSE;
334 EXLATEOBJ exlo;
335
336 DPRINT("Locking DCs\n");
337 ahDC[0] = hdcDst;
338 ahDC[1] = hdcSrc ;
339 GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
340 DCDest = apObj[0];
341 DCSrc = apObj[1];
342
343 if ((NULL == DCDest) || (NULL == DCSrc))
344 {
345 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
346 SetLastWin32Error(ERROR_INVALID_HANDLE);
347 if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
348 if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
349 return FALSE;
350 }
351
352 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
353 {
354 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
355 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
356 /* Yes, Windows really returns TRUE in this case */
357 return TRUE;
358 }
359
360 rcDest.left = xDst;
361 rcDest.top = yDst;
362 rcDest.right = rcDest.left + cxDst;
363 rcDest.bottom = rcDest.top + cyDst;
364 IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2);
365
366 rcDest.left += DCDest->ptlDCOrig.x;
367 rcDest.top += DCDest->ptlDCOrig.y;
368 rcDest.right += DCDest->ptlDCOrig.x;
369 rcDest.bottom += DCDest->ptlDCOrig.y;
370
371 rcSrc.left = xSrc;
372 rcSrc.top = ySrc;
373 rcSrc.right = rcSrc.left + cxSrc;
374 rcSrc.bottom = rcSrc.top + cySrc;
375 IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2);
376
377 rcSrc.left += DCSrc->ptlDCOrig.x;
378 rcSrc.top += DCSrc->ptlDCOrig.y;
379 rcSrc.right += DCSrc->ptlDCOrig.x;
380 rcSrc.bottom += DCSrc->ptlDCOrig.y;
381
382 /* Prepare for blit */
383 DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
384
385 BitmapDest = DCDest->dclevel.pSurface;
386 if (!BitmapDest)
387 {
388 goto done;
389 }
390
391 BitmapSrc = DCSrc->dclevel.pSurface;
392 if (!BitmapSrc)
393 {
394 goto done;
395 }
396
397 if (BitmapSrc->ppal)
398 {
399 GDIOBJ_IncrementShareCount(&BitmapSrc->ppal->BaseObject);
400 PalSourceGDI = BitmapSrc->ppal ;
401 }
402 else
403 PalSourceGDI = PALETTE_ShareLockPalette(pPrimarySurface->devinfo.hpalDefault) ;
404
405 if(!PalSourceGDI)
406 {
407 SetLastWin32Error(ERROR_INVALID_HANDLE);
408 goto done;
409 }
410
411 /* Translate Transparent (RGB) Color to the source palette */
412 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, PalSourceGDI, 0, 0, 0);
413 TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
414 EXLATEOBJ_vCleanup(&exlo);
415 PALETTE_ShareUnlockPalette(PalSourceGDI);
416
417 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
418
419 Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
420 DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
421 TransparentColor, 0);
422
423 EXLATEOBJ_vCleanup(&exlo);
424
425 done:
426 DC_vFinishBlit(DCDest, DCSrc);
427 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
428 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
429
430 return Ret;
431 }
432
433 /***********************************************************************
434 * MaskBlt
435 * Ported from WINE by sedwards 11-4-03
436 *
437 * Someone thought it would be faster to do it here and then switch back
438 * to GDI32. I dunno. Write a test and let me know.
439 * A. It should be in here!
440 */
441
442 static __inline BYTE
443 SwapROP3_SrcDst(BYTE bRop3)
444 {
445 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
446 }
447
448 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
449 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
450 #define DSTCOPY 0x00AA0029
451 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
452
453 BOOL APIENTRY
454 NtGdiMaskBlt(
455 HDC hdcDest,
456 INT nXDest,
457 INT nYDest,
458 INT nWidth,
459 INT nHeight,
460 HDC hdcSrc,
461 INT nXSrc,
462 INT nYSrc,
463 HBITMAP hbmMask,
464 INT xMask,
465 INT yMask,
466 DWORD dwRop,
467 IN DWORD crBackColor)
468 {
469 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
470 HDC hDCMask, hDC1, hDC2;
471 static const DWORD ROP3Table[256] =
472 {
473 0x00000042, 0x00010289,
474 0x00020C89, 0x000300AA,
475 0x00040C88, 0x000500A9,
476 0x00060865, 0x000702C5,
477 0x00080F08, 0x00090245,
478 0x000A0329, 0x000B0B2A,
479 0x000C0324, 0x000D0B25,
480 0x000E08A5, 0x000F0001,
481 0x00100C85, 0x001100A6,
482 0x00120868, 0x001302C8,
483 0x00140869, 0x001502C9,
484 0x00165CCA, 0x00171D54,
485 0x00180D59, 0x00191CC8,
486 0x001A06C5, 0x001B0768,
487 0x001C06CA, 0x001D0766,
488 0x001E01A5, 0x001F0385,
489 0x00200F09, 0x00210248,
490 0x00220326, 0x00230B24,
491 0x00240D55, 0x00251CC5,
492 0x002606C8, 0x00271868,
493 0x00280369, 0x002916CA,
494 0x002A0CC9, 0x002B1D58,
495 0x002C0784, 0x002D060A,
496 0x002E064A, 0x002F0E2A,
497 0x0030032A, 0x00310B28,
498 0x00320688, 0x00330008,
499 0x003406C4, 0x00351864,
500 0x003601A8, 0x00370388,
501 0x0038078A, 0x00390604,
502 0x003A0644, 0x003B0E24,
503 0x003C004A, 0x003D18A4,
504 0x003E1B24, 0x003F00EA,
505 0x00400F0A, 0x00410249,
506 0x00420D5D, 0x00431CC4,
507 0x00440328, 0x00450B29,
508 0x004606C6, 0x0047076A,
509 0x00480368, 0x004916C5,
510 0x004A0789, 0x004B0605,
511 0x004C0CC8, 0x004D1954,
512 0x004E0645, 0x004F0E25,
513 0x00500325, 0x00510B26,
514 0x005206C9, 0x00530764,
515 0x005408A9, 0x00550009,
516 0x005601A9, 0x00570389,
517 0x00580785, 0x00590609,
518 0x005A0049, 0x005B18A9,
519 0x005C0649, 0x005D0E29,
520 0x005E1B29, 0x005F00E9,
521 0x00600365, 0x006116C6,
522 0x00620786, 0x00630608,
523 0x00640788, 0x00650606,
524 0x00660046, 0x006718A8,
525 0x006858A6, 0x00690145,
526 0x006A01E9, 0x006B178A,
527 0x006C01E8, 0x006D1785,
528 0x006E1E28, 0x006F0C65,
529 0x00700CC5, 0x00711D5C,
530 0x00720648, 0x00730E28,
531 0x00740646, 0x00750E26,
532 0x00761B28, 0x007700E6,
533 0x007801E5, 0x00791786,
534 0x007A1E29, 0x007B0C68,
535 0x007C1E24, 0x007D0C69,
536 0x007E0955, 0x007F03C9,
537 0x008003E9, 0x00810975,
538 0x00820C49, 0x00831E04,
539 0x00840C48, 0x00851E05,
540 0x008617A6, 0x008701C5,
541 0x008800C6, 0x00891B08,
542 0x008A0E06, 0x008B0666,
543 0x008C0E08, 0x008D0668,
544 0x008E1D7C, 0x008F0CE5,
545 0x00900C45, 0x00911E08,
546 0x009217A9, 0x009301C4,
547 0x009417AA, 0x009501C9,
548 0x00960169, 0x0097588A,
549 0x00981888, 0x00990066,
550 0x009A0709, 0x009B07A8,
551 0x009C0704, 0x009D07A6,
552 0x009E16E6, 0x009F0345,
553 0x00A000C9, 0x00A11B05,
554 0x00A20E09, 0x00A30669,
555 0x00A41885, 0x00A50065,
556 0x00A60706, 0x00A707A5,
557 0x00A803A9, 0x00A90189,
558 0x00AA0029, 0x00AB0889,
559 0x00AC0744, 0x00AD06E9,
560 0x00AE0B06, 0x00AF0229,
561 0x00B00E05, 0x00B10665,
562 0x00B21974, 0x00B30CE8,
563 0x00B4070A, 0x00B507A9,
564 0x00B616E9, 0x00B70348,
565 0x00B8074A, 0x00B906E6,
566 0x00BA0B09, 0x00BB0226,
567 0x00BC1CE4, 0x00BD0D7D,
568 0x00BE0269, 0x00BF08C9,
569 0x00C000CA, 0x00C11B04,
570 0x00C21884, 0x00C3006A,
571 0x00C40E04, 0x00C50664,
572 0x00C60708, 0x00C707AA,
573 0x00C803A8, 0x00C90184,
574 0x00CA0749, 0x00CB06E4,
575 0x00CC0020, 0x00CD0888,
576 0x00CE0B08, 0x00CF0224,
577 0x00D00E0A, 0x00D1066A,
578 0x00D20705, 0x00D307A4,
579 0x00D41D78, 0x00D50CE9,
580 0x00D616EA, 0x00D70349,
581 0x00D80745, 0x00D906E8,
582 0x00DA1CE9, 0x00DB0D75,
583 0x00DC0B04, 0x00DD0228,
584 0x00DE0268, 0x00DF08C8,
585 0x00E003A5, 0x00E10185,
586 0x00E20746, 0x00E306EA,
587 0x00E40748, 0x00E506E5,
588 0x00E61CE8, 0x00E70D79,
589 0x00E81D74, 0x00E95CE6,
590 0x00EA02E9, 0x00EB0849,
591 0x00EC02E8, 0x00ED0848,
592 0x00EE0086, 0x00EF0A08,
593 0x00F00021, 0x00F10885,
594 0x00F20B05, 0x00F3022A,
595 0x00F40B0A, 0x00F50225,
596 0x00F60265, 0x00F708C5,
597 0x00F802E5, 0x00F90845,
598 0x00FA0089, 0x00FB0A09,
599 0x00FC008A, 0x00FD0A0A,
600 0x00FE02A9, 0x00FF0062,
601 };
602
603 if (!hbmMask)
604 return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0, 0);
605
606 /* 1. make mask bitmap's dc */
607 hDCMask = NtGdiCreateCompatibleDC(hdcDest);
608 hOldMaskBitmap = (HBITMAP)NtGdiSelectBitmap(hDCMask, hbmMask);
609
610 /* 2. make masked Background bitmap */
611
612 /* 2.1 make bitmap */
613 hDC1 = NtGdiCreateCompatibleDC(hdcDest);
614 hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
615 hOldBitmap2 = (HBITMAP)NtGdiSelectBitmap(hDC1, hBitmap2);
616
617 /* 2.2 draw dest bitmap and mask */
618 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0);
619 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0);
620 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE, 0, 0);
621
622 /* 3. make masked Foreground bitmap */
623
624 /* 3.1 make bitmap */
625 hDC2 = NtGdiCreateCompatibleDC(hdcDest);
626 hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
627 hOldBitmap3 = (HBITMAP)NtGdiSelectBitmap(hDC2, hBitmap3);
628
629 /* 3.2 draw src bitmap and mask */
630 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0);
631 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0);
632 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND, 0, 0);
633
634 /* 4. combine both and copy the result to hdcDest */
635 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT, 0, 0);
636 NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY, 0, 0);
637
638 /* 5. restore all objects */
639 NtGdiSelectBitmap(hDCMask, hOldMaskBitmap);
640 NtGdiSelectBitmap(hDC1, hOldBitmap2);
641 NtGdiSelectBitmap(hDC2, hOldBitmap3);
642
643 /* 6. delete all temp objects */
644 GreDeleteObject(hBitmap2);
645 GreDeleteObject(hBitmap3);
646
647 NtGdiDeleteObjectApp(hDC1);
648 NtGdiDeleteObjectApp(hDC2);
649 NtGdiDeleteObjectApp(hDCMask);
650
651 return TRUE;
652 }
653
654 BOOL
655 APIENTRY
656 NtGdiPlgBlt(
657 IN HDC hdcTrg,
658 IN LPPOINT pptlTrg,
659 IN HDC hdcSrc,
660 IN INT xSrc,
661 IN INT ySrc,
662 IN INT cxSrc,
663 IN INT cySrc,
664 IN HBITMAP hbmMask,
665 IN INT xMask,
666 IN INT yMask,
667 IN DWORD crBackColor)
668 {
669 UNIMPLEMENTED;
670 return FALSE;
671 }
672
673 BOOL APIENTRY
674 GreStretchBltMask(
675 HDC hDCDest,
676 INT XOriginDest,
677 INT YOriginDest,
678 INT WidthDest,
679 INT HeightDest,
680 HDC hDCSrc,
681 INT XOriginSrc,
682 INT YOriginSrc,
683 INT WidthSrc,
684 INT HeightSrc,
685 DWORD ROP,
686 IN DWORD dwBackColor,
687 HDC hDCMask,
688 INT XOriginMask,
689 INT YOriginMask)
690 {
691 PDC DCDest;
692 PDC DCSrc = NULL;
693 PDC DCMask = NULL;
694 HDC ahDC[3];
695 PGDIOBJ apObj[3];
696 PDC_ATTR pdcattr;
697 SURFACE *BitmapDest, *BitmapSrc = NULL;
698 SURFACE *BitmapMask = NULL;
699 RECTL DestRect;
700 RECTL SourceRect;
701 POINTL MaskPoint;
702 BOOL Status = FALSE;
703 EXLATEOBJ exlo;
704 XLATEOBJ *XlateObj = NULL;
705 POINTL BrushOrigin;
706 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
707
708 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
709 {
710 SetLastWin32Error(ERROR_INVALID_PARAMETER);
711 return FALSE;
712 }
713
714 DPRINT("Locking DCs\n");
715 ahDC[0] = hDCDest;
716 ahDC[1] = hDCSrc ;
717 ahDC[2] = hDCMask ;
718 GDIOBJ_LockMultipleObjs(3, ahDC, apObj);
719 DCDest = apObj[0];
720 DCSrc = apObj[1];
721 DCMask = apObj[2];
722
723 if (NULL == DCDest)
724 {
725 if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
726 if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
727 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
728 return FALSE;
729 }
730
731 if (DCDest->dctype == DC_TYPE_INFO)
732 {
733 if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
734 if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
735 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
736 /* Yes, Windows really returns TRUE in this case */
737 return TRUE;
738 }
739
740 if (UsesSource)
741 {
742 if (NULL == DCSrc)
743 {
744 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
745 if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
746 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
747 return FALSE;
748 }
749 if (DCSrc->dctype == DC_TYPE_INFO)
750 {
751 GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
752 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
753 if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
754 /* Yes, Windows really returns TRUE in this case */
755 return TRUE;
756 }
757 }
758 else if(DCSrc)
759 {
760 DPRINT1("Getting a valid Source handle without using source!!!\n");
761 GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
762 DCSrc = NULL ;
763 }
764
765 pdcattr = DCDest->pdcattr;
766
767 DestRect.left = XOriginDest;
768 DestRect.top = YOriginDest;
769 DestRect.right = XOriginDest+WidthDest;
770 DestRect.bottom = YOriginDest+HeightDest;
771 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
772
773 DestRect.left += DCDest->ptlDCOrig.x;
774 DestRect.top += DCDest->ptlDCOrig.y;
775 DestRect.right += DCDest->ptlDCOrig.x;
776 DestRect.bottom += DCDest->ptlDCOrig.y;
777
778 SourceRect.left = XOriginSrc;
779 SourceRect.top = YOriginSrc;
780 SourceRect.right = XOriginSrc+WidthSrc;
781 SourceRect.bottom = YOriginSrc+HeightSrc;
782
783 if (UsesSource)
784 {
785 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
786
787 SourceRect.left += DCSrc->ptlDCOrig.x;
788 SourceRect.top += DCSrc->ptlDCOrig.y;
789 SourceRect.right += DCSrc->ptlDCOrig.x;
790 SourceRect.bottom += DCSrc->ptlDCOrig.y;
791 }
792
793 BrushOrigin.x = 0;
794 BrushOrigin.y = 0;
795
796 /* Only prepare Source and Dest, hdcMask represents a DIB */
797 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
798
799 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
800 DC_vUpdateFillBrush(DCDest);
801
802 /* Determine surfaces to be used in the bitblt */
803 BitmapDest = DCDest->dclevel.pSurface;
804 if (BitmapDest == NULL)
805 goto failed;
806 if (UsesSource)
807 {
808 BitmapSrc = DCSrc->dclevel.pSurface;
809 if (BitmapSrc == NULL)
810 goto failed;
811
812 /* Create the XLATEOBJ. */
813 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
814 XlateObj = &exlo.xlo;
815 }
816
817 /* Offset the brush */
818 BrushOrigin.x += DCDest->ptlDCOrig.x;
819 BrushOrigin.y += DCDest->ptlDCOrig.y;
820
821 /* Make mask surface for source surface */
822 if (BitmapSrc && DCMask)
823 {
824 BitmapMask = DCMask->dclevel.pSurface;
825 if (BitmapMask &&
826 (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
827 BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
828 {
829 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
830 BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
831 WidthSrc, HeightSrc);
832 EXLATEOBJ_vCleanup(&exlo);
833 goto failed;
834 }
835 /* Create mask offset point */
836 MaskPoint.x = XOriginMask;
837 MaskPoint.y = YOriginMask;
838 IntLPtoDP(DCMask, &MaskPoint, 1);
839 MaskPoint.x += DCMask->ptlDCOrig.x;
840 MaskPoint.y += DCMask->ptlDCOrig.x;
841 }
842
843 /* Perform the bitblt operation */
844 Status = IntEngStretchBlt(&BitmapDest->SurfObj,
845 &BitmapSrc->SurfObj,
846 BitmapMask ? &BitmapMask->SurfObj : NULL,
847 DCDest->rosdc.CombinedClip,
848 XlateObj,
849 &DestRect,
850 &SourceRect,
851 BitmapMask ? &MaskPoint : NULL,
852 &DCDest->eboFill.BrushObject,
853 &BrushOrigin,
854 ROP3_TO_ROP4(ROP));
855 if (UsesSource)
856 {
857 EXLATEOBJ_vCleanup(&exlo);
858 }
859
860 failed:
861 DC_vFinishBlit(DCDest, DCSrc);
862 if (UsesSource)
863 {
864 DC_UnlockDc(DCSrc);
865 }
866 if (DCMask)
867 {
868 DC_UnlockDc(DCMask);
869 }
870 DC_UnlockDc(DCDest);
871
872 return Status;
873 }
874
875
876 BOOL APIENTRY
877 NtGdiStretchBlt(
878 HDC hDCDest,
879 INT XOriginDest,
880 INT YOriginDest,
881 INT WidthDest,
882 INT HeightDest,
883 HDC hDCSrc,
884 INT XOriginSrc,
885 INT YOriginSrc,
886 INT WidthSrc,
887 INT HeightSrc,
888 DWORD ROP,
889 IN DWORD dwBackColor)
890 {
891 return GreStretchBltMask(
892 hDCDest,
893 XOriginDest,
894 YOriginDest,
895 WidthDest,
896 HeightDest,
897 hDCSrc,
898 XOriginSrc,
899 YOriginSrc,
900 WidthSrc,
901 HeightSrc,
902 ROP,
903 dwBackColor,
904 NULL,
905 0,
906 0);
907 }
908
909
910 BOOL FASTCALL
911 IntPatBlt(
912 PDC pdc,
913 INT XLeft,
914 INT YLeft,
915 INT Width,
916 INT Height,
917 DWORD dwRop,
918 PBRUSH pbrush)
919 {
920 RECTL DestRect;
921 SURFACE *psurf;
922 EBRUSHOBJ eboFill ;
923 POINTL BrushOrigin;
924 BOOL ret;
925
926 ASSERT(pbrush);
927
928 if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
929 {
930 return TRUE;
931 }
932
933 if (Width > 0)
934 {
935 DestRect.left = XLeft;
936 DestRect.right = XLeft + Width;
937 }
938 else
939 {
940 DestRect.left = XLeft + Width + 1;
941 DestRect.right = XLeft + 1;
942 }
943
944 if (Height > 0)
945 {
946 DestRect.top = YLeft;
947 DestRect.bottom = YLeft + Height;
948 }
949 else
950 {
951 DestRect.top = YLeft + Height + 1;
952 DestRect.bottom = YLeft + 1;
953 }
954
955 IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);
956
957 DestRect.left += pdc->ptlDCOrig.x;
958 DestRect.top += pdc->ptlDCOrig.y;
959 DestRect.right += pdc->ptlDCOrig.x;
960 DestRect.bottom += pdc->ptlDCOrig.y;
961
962 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
963 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
964
965 DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
966
967 psurf = pdc->dclevel.pSurface;
968
969 if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
970 DC_vUpdateFillBrush(pdc);
971
972 EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
973
974 ret = IntEngBitBlt(
975 &psurf->SurfObj,
976 NULL,
977 NULL,
978 pdc->rosdc.CombinedClip,
979 NULL,
980 &DestRect,
981 NULL,
982 NULL,
983 &eboFill.BrushObject,
984 &BrushOrigin,
985 ROP3_TO_ROP4(dwRop));
986
987 DC_vFinishBlit(pdc, NULL);
988
989 EBRUSHOBJ_vCleanup(&eboFill);
990
991 return ret;
992 }
993
994 BOOL FASTCALL
995 IntGdiPolyPatBlt(
996 HDC hDC,
997 DWORD dwRop,
998 PPATRECT pRects,
999 INT cRects,
1000 ULONG Reserved)
1001 {
1002 INT i;
1003 PBRUSH pbrush;
1004 PDC pdc;
1005
1006 pdc = DC_LockDc(hDC);
1007 if (!pdc)
1008 {
1009 SetLastWin32Error(ERROR_INVALID_HANDLE);
1010 return FALSE;
1011 }
1012
1013 if (pdc->dctype == DC_TYPE_INFO)
1014 {
1015 DC_UnlockDc(pdc);
1016 /* Yes, Windows really returns TRUE in this case */
1017 return TRUE;
1018 }
1019
1020 for (i = 0; i < cRects; i++)
1021 {
1022 pbrush = BRUSH_LockBrush(pRects->hBrush);
1023 if(pbrush != NULL)
1024 {
1025 IntPatBlt(
1026 pdc,
1027 pRects->r.left,
1028 pRects->r.top,
1029 pRects->r.right,
1030 pRects->r.bottom,
1031 dwRop,
1032 pbrush);
1033 BRUSH_UnlockBrush(pbrush);
1034 }
1035 pRects++;
1036 }
1037
1038 DC_UnlockDc(pdc);
1039
1040 return TRUE;
1041 }
1042
1043
1044 BOOL APIENTRY
1045 NtGdiPatBlt(
1046 HDC hDC,
1047 INT XLeft,
1048 INT YLeft,
1049 INT Width,
1050 INT Height,
1051 DWORD ROP)
1052 {
1053 PBRUSH pbrush;
1054 DC *dc;
1055 PDC_ATTR pdcattr;
1056 BOOL ret;
1057
1058 BOOL UsesSource = ROP3_USES_SOURCE(ROP);
1059 if (UsesSource)
1060 {
1061 /* in this case we call on GdiMaskBlt */
1062 return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0);
1063 }
1064
1065 dc = DC_LockDc(hDC);
1066 if (dc == NULL)
1067 {
1068 SetLastWin32Error(ERROR_INVALID_HANDLE);
1069 return FALSE;
1070 }
1071 if (dc->dctype == DC_TYPE_INFO)
1072 {
1073 DC_UnlockDc(dc);
1074 /* Yes, Windows really returns TRUE in this case */
1075 return TRUE;
1076 }
1077
1078 pdcattr = dc->pdcattr;
1079
1080 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
1081 DC_vUpdateFillBrush(dc);
1082
1083 pbrush = BRUSH_LockBrush(pdcattr->hbrush);
1084 if (pbrush == NULL)
1085 {
1086 SetLastWin32Error(ERROR_INVALID_HANDLE);
1087 DC_UnlockDc(dc);
1088 return FALSE;
1089 }
1090
1091 ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush);
1092
1093 BRUSH_UnlockBrush(pbrush);
1094 DC_UnlockDc(dc);
1095
1096 return ret;
1097 }
1098
1099 BOOL APIENTRY
1100 NtGdiPolyPatBlt(
1101 HDC hDC,
1102 DWORD dwRop,
1103 IN PPOLYPATBLT pRects,
1104 IN DWORD cRects,
1105 IN DWORD Mode)
1106 {
1107 PPATRECT rb = NULL;
1108 NTSTATUS Status = STATUS_SUCCESS;
1109 BOOL Ret;
1110
1111 if (cRects > 0)
1112 {
1113 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, TAG_PATBLT);
1114 if (!rb)
1115 {
1116 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1117 return FALSE;
1118 }
1119 _SEH2_TRY
1120 {
1121 ProbeForRead(pRects,
1122 cRects * sizeof(PATRECT),
1123 1);
1124 RtlCopyMemory(rb,
1125 pRects,
1126 cRects * sizeof(PATRECT));
1127 }
1128 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1129 {
1130 Status = _SEH2_GetExceptionCode();
1131 }
1132 _SEH2_END;
1133
1134 if (!NT_SUCCESS(Status))
1135 {
1136 ExFreePoolWithTag(rb, TAG_PATBLT);
1137 SetLastNtError(Status);
1138 return FALSE;
1139 }
1140 }
1141
1142 Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode);
1143
1144 if (cRects > 0)
1145 ExFreePoolWithTag(rb, TAG_PATBLT);
1146
1147 return Ret;
1148 }