- Synchronize up to trunk's revision r57864.
[reactos.git] / win32ss / gdi / ntgdi / patblt.c
1 /*
2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Bit blit functions
5 * FILE: subsys/win32k/objects/bitblt.c
6 * PROGRAMER: Unknown
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #define ROP_USES_SOURCE(Rop) (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000)))
15 #define ROP_USES_MASK(Rop) (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8))
16
17 #define FIXUP_ROP(Rop) if(((Rop) & 0xFF000000) == 0) Rop = MAKEROP4((Rop), (Rop))
18 #define ROP_TO_ROP4(Rop) ((Rop) >> 16)
19
20 BOOL APIENTRY
21 NtGdiAlphaBlend(
22 HDC hDCDest,
23 LONG XOriginDest,
24 LONG YOriginDest,
25 LONG WidthDest,
26 LONG HeightDest,
27 HDC hDCSrc,
28 LONG XOriginSrc,
29 LONG YOriginSrc,
30 LONG WidthSrc,
31 LONG HeightSrc,
32 BLENDFUNCTION BlendFunc,
33 HANDLE hcmXform)
34 {
35 PDC DCDest;
36 PDC DCSrc;
37 HDC ahDC[2];
38 PGDIOBJ apObj[2];
39 SURFACE *BitmapDest, *BitmapSrc;
40 RECTL DestRect, SourceRect;
41 BOOL bResult;
42 EXLATEOBJ exlo;
43 BLENDOBJ BlendObj;
44 BlendObj.BlendFunction = BlendFunc;
45
46 if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0)
47 {
48 EngSetLastError(ERROR_INVALID_PARAMETER);
49 return FALSE;
50 }
51
52 DPRINT("Locking DCs\n");
53 ahDC[0] = hDCDest;
54 ahDC[1] = hDCSrc ;
55 if (!GDIOBJ_bLockMultipleObjects(2, ahDC, apObj, GDIObjType_DC_TYPE))
56 {
57 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
58 EngSetLastError(ERROR_INVALID_HANDLE);
59 return FALSE;
60 }
61 DCDest = apObj[0];
62 DCSrc = apObj[1];
63
64 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
65 {
66 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
67 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
68 /* Yes, Windows really returns TRUE in this case */
69 return TRUE;
70 }
71
72 DestRect.left = XOriginDest;
73 DestRect.top = YOriginDest;
74 DestRect.right = XOriginDest + WidthDest;
75 DestRect.bottom = YOriginDest + HeightDest;
76 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
77
78 DestRect.left += DCDest->ptlDCOrig.x;
79 DestRect.top += DCDest->ptlDCOrig.y;
80 DestRect.right += DCDest->ptlDCOrig.x;
81 DestRect.bottom += DCDest->ptlDCOrig.y;
82
83 SourceRect.left = XOriginSrc;
84 SourceRect.top = YOriginSrc;
85 SourceRect.right = XOriginSrc + WidthSrc;
86 SourceRect.bottom = YOriginSrc + HeightSrc;
87 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
88
89 SourceRect.left += DCSrc->ptlDCOrig.x;
90 SourceRect.top += DCSrc->ptlDCOrig.y;
91 SourceRect.right += DCSrc->ptlDCOrig.x;
92 SourceRect.bottom += DCSrc->ptlDCOrig.y;
93
94 if (!DestRect.right ||
95 !DestRect.bottom ||
96 !SourceRect.right ||
97 !SourceRect.bottom)
98 {
99 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
100 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
101 return TRUE;
102 }
103
104 /* Prepare DCs for blit */
105 DPRINT("Preparing DCs for blit\n");
106 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
107
108 /* Determine surfaces to be used in the bitblt */
109 BitmapDest = DCDest->dclevel.pSurface;
110 if (!BitmapDest)
111 {
112 bResult = FALSE ;
113 goto leave ;
114 }
115
116 BitmapSrc = DCSrc->dclevel.pSurface;
117 if (!BitmapSrc)
118 {
119 bResult = FALSE;
120 goto leave;
121 }
122
123 /* Create the XLATEOBJ. */
124 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
125
126 /* Perform the alpha blend operation */
127 DPRINT("Performing the alpha blend\n");
128 bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
129 &BitmapSrc->SurfObj,
130 DCDest->rosdc.CombinedClip,
131 &exlo.xlo,
132 &DestRect,
133 &SourceRect,
134 &BlendObj);
135
136 EXLATEOBJ_vCleanup(&exlo);
137 leave :
138 DPRINT("Finishing blit\n");
139 DC_vFinishBlit(DCDest, DCSrc);
140 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
141 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
142
143 return bResult;
144 }
145
146 BOOL APIENTRY
147 NtGdiBitBlt(
148 HDC hDCDest,
149 INT XDest,
150 INT YDest,
151 INT Width,
152 INT Height,
153 HDC hDCSrc,
154 INT XSrc,
155 INT YSrc,
156 DWORD ROP,
157 IN DWORD crBackColor,
158 IN FLONG fl)
159 {
160 /* Forward to NtGdiMaskBlt */
161 // TODO: What's fl for?
162 return NtGdiMaskBlt(hDCDest,
163 XDest,
164 YDest,
165 Width,
166 Height,
167 hDCSrc,
168 XSrc,
169 YSrc,
170 NULL,
171 0,
172 0,
173 ROP,
174 crBackColor);
175 }
176
177 BOOL APIENTRY
178 NtGdiTransparentBlt(
179 HDC hdcDst,
180 INT xDst,
181 INT yDst,
182 INT cxDst,
183 INT cyDst,
184 HDC hdcSrc,
185 INT xSrc,
186 INT ySrc,
187 INT cxSrc,
188 INT cySrc,
189 COLORREF TransColor)
190 {
191 PDC DCDest, DCSrc;
192 HDC ahDC[2];
193 PGDIOBJ apObj[2];
194 RECTL rcDest, rcSrc;
195 SURFACE *BitmapDest, *BitmapSrc = NULL;
196 ULONG TransparentColor = 0;
197 BOOL Ret = FALSE;
198 EXLATEOBJ exlo;
199
200 DPRINT("Locking DCs\n");
201 ahDC[0] = hdcDst;
202 ahDC[1] = hdcSrc ;
203 if (!GDIOBJ_bLockMultipleObjects(2, ahDC, apObj, GDIObjType_DC_TYPE))
204 {
205 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
206 EngSetLastError(ERROR_INVALID_HANDLE);
207 return FALSE;
208 }
209 DCDest = apObj[0];
210 DCSrc = apObj[1];
211
212 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
213 {
214 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
215 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
216 /* Yes, Windows really returns TRUE in this case */
217 return TRUE;
218 }
219
220 rcDest.left = xDst;
221 rcDest.top = yDst;
222 rcDest.right = rcDest.left + cxDst;
223 rcDest.bottom = rcDest.top + cyDst;
224 IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2);
225
226 rcDest.left += DCDest->ptlDCOrig.x;
227 rcDest.top += DCDest->ptlDCOrig.y;
228 rcDest.right += DCDest->ptlDCOrig.x;
229 rcDest.bottom += DCDest->ptlDCOrig.y;
230
231 rcSrc.left = xSrc;
232 rcSrc.top = ySrc;
233 rcSrc.right = rcSrc.left + cxSrc;
234 rcSrc.bottom = rcSrc.top + cySrc;
235 IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2);
236
237 rcSrc.left += DCSrc->ptlDCOrig.x;
238 rcSrc.top += DCSrc->ptlDCOrig.y;
239 rcSrc.right += DCSrc->ptlDCOrig.x;
240 rcSrc.bottom += DCSrc->ptlDCOrig.y;
241
242 /* Prepare for blit */
243 DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
244
245 BitmapDest = DCDest->dclevel.pSurface;
246 if (!BitmapDest)
247 {
248 goto done;
249 }
250
251 BitmapSrc = DCSrc->dclevel.pSurface;
252 if (!BitmapSrc)
253 {
254 goto done;
255 }
256
257 /* Translate Transparent (RGB) Color to the source palette */
258 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0);
259 TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
260 EXLATEOBJ_vCleanup(&exlo);
261
262 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
263
264 Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
265 DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
266 TransparentColor, 0);
267
268 EXLATEOBJ_vCleanup(&exlo);
269
270 done:
271 DC_vFinishBlit(DCDest, DCSrc);
272 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
273 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
274
275 return Ret;
276 }
277
278 BOOL APIENTRY
279 NtGdiMaskBlt(
280 HDC hdcDest,
281 INT nXDest,
282 INT nYDest,
283 INT nWidth,
284 INT nHeight,
285 HDC hdcSrc,
286 INT nXSrc,
287 INT nYSrc,
288 HBITMAP hbmMask,
289 INT xMask,
290 INT yMask,
291 DWORD dwRop,
292 IN DWORD crBackColor)
293 {
294 PDC DCDest;
295 PDC DCSrc = NULL;
296 HDC ahDC[2];
297 PGDIOBJ apObj[2];
298 PDC_ATTR pdcattr = NULL;
299 SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL;
300 RECTL DestRect, SourceRect;
301 POINTL SourcePoint, MaskPoint;
302 BOOL Status = FALSE;
303 EXLATEOBJ exlo;
304 XLATEOBJ *XlateObj = NULL;
305 BOOL UsesSource = ROP_USES_SOURCE(dwRop);
306 BOOL UsesMask;
307
308 FIXUP_ROP(dwRop);
309
310 UsesMask = ROP_USES_MASK(dwRop);
311
312 //DPRINT1("dwRop : 0x%08x\n", dwRop);
313 if (!hdcDest || (UsesSource && !hdcSrc))
314 {
315 EngSetLastError(ERROR_INVALID_PARAMETER);
316 return FALSE;
317 }
318
319 /* Take care of mask bitmap */
320 if(hbmMask)
321 {
322 psurfMask = SURFACE_ShareLockSurface(hbmMask);
323 if(!psurfMask)
324 {
325 EngSetLastError(ERROR_INVALID_HANDLE);
326 return FALSE;
327 }
328 }
329
330 if(UsesMask)
331 {
332 if(!psurfMask)
333 {
334 EngSetLastError(ERROR_INVALID_PARAMETER);
335 return FALSE;
336 }
337 if(gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1)
338 {
339 EngSetLastError(ERROR_INVALID_PARAMETER);
340 SURFACE_ShareUnlockSurface(psurfMask);
341 return FALSE;
342 }
343 }
344 else if(psurfMask)
345 {
346 DPRINT1("Getting Mask bitmap without needing it?\n");
347 SURFACE_ShareUnlockSurface(psurfMask);
348 psurfMask = NULL;
349 }
350 MaskPoint.x = xMask;
351 MaskPoint.y = yMask;
352
353 /* Take care of source and destination bitmap */
354 DPRINT("Locking DCs\n");
355 ahDC[0] = hdcDest;
356 ahDC[1] = UsesSource ? hdcSrc : NULL;
357 if (!GDIOBJ_bLockMultipleObjects(2, ahDC, apObj, GDIObjType_DC_TYPE))
358 {
359 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
360 EngSetLastError(ERROR_INVALID_HANDLE);
361 return FALSE;
362 }
363 DCDest = apObj[0];
364 DCSrc = apObj[1];
365
366 ASSERT(DCDest);
367 if (NULL == DCDest)
368 {
369 if(DCSrc) DC_UnlockDc(DCSrc);
370 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcDest);
371 return FALSE;
372 }
373
374 if (DCDest->dctype == DC_TYPE_INFO)
375 {
376 if(DCSrc) DC_UnlockDc(DCSrc);
377 DC_UnlockDc(DCDest);
378 /* Yes, Windows really returns TRUE in this case */
379 return TRUE;
380 }
381
382 if (UsesSource)
383 {
384 ASSERT(DCSrc);
385 if (DCSrc->dctype == DC_TYPE_INFO)
386 {
387 DC_UnlockDc(DCDest);
388 DC_UnlockDc(DCSrc);
389 /* Yes, Windows really returns TRUE in this case */
390 return TRUE;
391 }
392 }
393
394 pdcattr = DCDest->pdcattr;
395
396 DestRect.left = nXDest;
397 DestRect.top = nYDest;
398 DestRect.right = nXDest + nWidth;
399 DestRect.bottom = nYDest + nHeight;
400 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
401
402 DestRect.left += DCDest->ptlDCOrig.x;
403 DestRect.top += DCDest->ptlDCOrig.y;
404 DestRect.right += DCDest->ptlDCOrig.x;
405 DestRect.bottom += DCDest->ptlDCOrig.y;
406
407 SourcePoint.x = nXSrc;
408 SourcePoint.y = nYSrc;
409
410 if (UsesSource)
411 {
412 IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);
413
414 SourcePoint.x += DCSrc->ptlDCOrig.x;
415 SourcePoint.y += DCSrc->ptlDCOrig.y;
416 /* Calculate Source Rect */
417 SourceRect.left = SourcePoint.x;
418 SourceRect.top = SourcePoint.y;
419 SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
420 SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
421 }
422
423 /* Prepare blit */
424 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
425
426 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
427 DC_vUpdateFillBrush(DCDest);
428
429 /* Determine surfaces to be used in the bitblt */
430 BitmapDest = DCDest->dclevel.pSurface;
431 if (!BitmapDest)
432 goto cleanup;
433
434 if (UsesSource)
435 {
436 {
437 BitmapSrc = DCSrc->dclevel.pSurface;
438 if (!BitmapSrc)
439 goto cleanup;
440 }
441 }
442
443 /* Create the XLATEOBJ. */
444 if (UsesSource)
445 {
446 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
447 XlateObj = &exlo.xlo;
448 }
449
450
451 /* Perform the bitblt operation */
452 Status = IntEngBitBlt(&BitmapDest->SurfObj,
453 BitmapSrc ? &BitmapSrc->SurfObj : NULL,
454 psurfMask ? &psurfMask->SurfObj : NULL,
455 DCDest->rosdc.CombinedClip,
456 XlateObj,
457 &DestRect,
458 &SourcePoint,
459 &MaskPoint,
460 &DCDest->eboFill.BrushObject,
461 &DCDest->dclevel.pbrFill->ptOrigin,
462 ROP_TO_ROP4(dwRop));
463
464 if (UsesSource)
465 EXLATEOBJ_vCleanup(&exlo);
466 cleanup:
467 DC_vFinishBlit(DCDest, DCSrc);
468 if (UsesSource)
469 {
470 DC_UnlockDc(DCSrc);
471 }
472 DC_UnlockDc(DCDest);
473 if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
474
475 return Status;
476 }
477
478 BOOL
479 APIENTRY
480 NtGdiPlgBlt(
481 IN HDC hdcTrg,
482 IN LPPOINT pptlTrg,
483 IN HDC hdcSrc,
484 IN INT xSrc,
485 IN INT ySrc,
486 IN INT cxSrc,
487 IN INT cySrc,
488 IN HBITMAP hbmMask,
489 IN INT xMask,
490 IN INT yMask,
491 IN DWORD crBackColor)
492 {
493 UNIMPLEMENTED;
494 return FALSE;
495 }
496
497 BOOL APIENTRY
498 GreStretchBltMask(
499 HDC hDCDest,
500 INT XOriginDest,
501 INT YOriginDest,
502 INT WidthDest,
503 INT HeightDest,
504 HDC hDCSrc,
505 INT XOriginSrc,
506 INT YOriginSrc,
507 INT WidthSrc,
508 INT HeightSrc,
509 DWORD ROP,
510 IN DWORD dwBackColor,
511 HDC hDCMask,
512 INT XOriginMask,
513 INT YOriginMask)
514 {
515 PDC DCDest;
516 PDC DCSrc = NULL;
517 PDC DCMask = NULL;
518 HDC ahDC[3];
519 PGDIOBJ apObj[3];
520 PDC_ATTR pdcattr;
521 SURFACE *BitmapDest, *BitmapSrc = NULL;
522 SURFACE *BitmapMask = NULL;
523 RECTL DestRect;
524 RECTL SourceRect;
525 POINTL MaskPoint;
526 BOOL Status = FALSE;
527 EXLATEOBJ exlo;
528 XLATEOBJ *XlateObj = NULL;
529 POINTL BrushOrigin;
530 BOOL UsesSource;
531 BOOL UsesMask;
532
533 FIXUP_ROP(ROP);
534 UsesSource = ROP_USES_SOURCE(ROP);
535 UsesMask = ROP_USES_MASK(ROP);
536
537 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
538 {
539 EngSetLastError(ERROR_INVALID_PARAMETER);
540 return TRUE;
541 }
542
543 if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask))
544 {
545 EngSetLastError(ERROR_INVALID_PARAMETER);
546 return FALSE;
547 }
548
549 ahDC[0] = hDCDest;
550 ahDC[1] = UsesSource ? hDCSrc : NULL;
551 ahDC[2] = UsesMask ? hDCMask : NULL;
552 if (!GDIOBJ_bLockMultipleObjects(3, ahDC, apObj, GDIObjType_DC_TYPE))
553 {
554 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
555 EngSetLastError(ERROR_INVALID_HANDLE);
556 return FALSE;
557 }
558 DCDest = apObj[0];
559 DCSrc = apObj[1];
560 DCMask = apObj[2];
561
562 if (DCDest->dctype == DC_TYPE_INFO)
563 {
564 if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
565 if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
566 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
567 /* Yes, Windows really returns TRUE in this case */
568 return TRUE;
569 }
570
571 if (UsesSource)
572 {
573 if (DCSrc->dctype == DC_TYPE_INFO)
574 {
575 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
576 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
577 if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
578 /* Yes, Windows really returns TRUE in this case */
579 return TRUE;
580 }
581 }
582
583 pdcattr = DCDest->pdcattr;
584
585 DestRect.left = XOriginDest;
586 DestRect.top = YOriginDest;
587 DestRect.right = XOriginDest+WidthDest;
588 DestRect.bottom = YOriginDest+HeightDest;
589 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
590
591 DestRect.left += DCDest->ptlDCOrig.x;
592 DestRect.top += DCDest->ptlDCOrig.y;
593 DestRect.right += DCDest->ptlDCOrig.x;
594 DestRect.bottom += DCDest->ptlDCOrig.y;
595
596 SourceRect.left = XOriginSrc;
597 SourceRect.top = YOriginSrc;
598 SourceRect.right = XOriginSrc+WidthSrc;
599 SourceRect.bottom = YOriginSrc+HeightSrc;
600
601 if (UsesSource)
602 {
603 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
604
605 SourceRect.left += DCSrc->ptlDCOrig.x;
606 SourceRect.top += DCSrc->ptlDCOrig.y;
607 SourceRect.right += DCSrc->ptlDCOrig.x;
608 SourceRect.bottom += DCSrc->ptlDCOrig.y;
609 }
610
611 BrushOrigin.x = 0;
612 BrushOrigin.y = 0;
613
614 /* Only prepare Source and Dest, hdcMask represents a DIB */
615 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
616
617 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
618 DC_vUpdateFillBrush(DCDest);
619
620 /* Determine surfaces to be used in the bitblt */
621 BitmapDest = DCDest->dclevel.pSurface;
622 if (BitmapDest == NULL)
623 goto failed;
624 if (UsesSource)
625 {
626 BitmapSrc = DCSrc->dclevel.pSurface;
627 if (BitmapSrc == NULL)
628 goto failed;
629
630 /* Create the XLATEOBJ. */
631 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
632 XlateObj = &exlo.xlo;
633 }
634
635 /* Offset the brush */
636 BrushOrigin.x += DCDest->ptlDCOrig.x;
637 BrushOrigin.y += DCDest->ptlDCOrig.y;
638
639 /* Make mask surface for source surface */
640 if (BitmapSrc && DCMask)
641 {
642 BitmapMask = DCMask->dclevel.pSurface;
643 if (BitmapMask &&
644 (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
645 BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
646 {
647 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
648 BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
649 WidthSrc, HeightSrc);
650 EXLATEOBJ_vCleanup(&exlo);
651 goto failed;
652 }
653 /* Create mask offset point */
654 MaskPoint.x = XOriginMask;
655 MaskPoint.y = YOriginMask;
656 IntLPtoDP(DCMask, &MaskPoint, 1);
657 MaskPoint.x += DCMask->ptlDCOrig.x;
658 MaskPoint.y += DCMask->ptlDCOrig.y;
659 }
660
661 /* Perform the bitblt operation */
662 Status = IntEngStretchBlt(&BitmapDest->SurfObj,
663 &BitmapSrc->SurfObj,
664 BitmapMask ? &BitmapMask->SurfObj : NULL,
665 DCDest->rosdc.CombinedClip,
666 XlateObj,
667 &DestRect,
668 &SourceRect,
669 BitmapMask ? &MaskPoint : NULL,
670 &DCDest->eboFill.BrushObject,
671 &BrushOrigin,
672 ROP_TO_ROP4(ROP));
673 if (UsesSource)
674 {
675 EXLATEOBJ_vCleanup(&exlo);
676 }
677
678 failed:
679 DC_vFinishBlit(DCDest, DCSrc);
680 if (UsesSource)
681 {
682 DC_UnlockDc(DCSrc);
683 }
684 if (DCMask)
685 {
686 DC_UnlockDc(DCMask);
687 }
688 DC_UnlockDc(DCDest);
689
690 return Status;
691 }
692
693
694 BOOL APIENTRY
695 NtGdiStretchBlt(
696 HDC hDCDest,
697 INT XOriginDest,
698 INT YOriginDest,
699 INT WidthDest,
700 INT HeightDest,
701 HDC hDCSrc,
702 INT XOriginSrc,
703 INT YOriginSrc,
704 INT WidthSrc,
705 INT HeightSrc,
706 DWORD ROP,
707 IN DWORD dwBackColor)
708 {
709 return GreStretchBltMask(
710 hDCDest,
711 XOriginDest,
712 YOriginDest,
713 WidthDest,
714 HeightDest,
715 hDCSrc,
716 XOriginSrc,
717 YOriginSrc,
718 WidthSrc,
719 HeightSrc,
720 ROP,
721 dwBackColor,
722 NULL,
723 0,
724 0);
725 }
726
727
728 BOOL FASTCALL
729 IntPatBlt(
730 PDC pdc,
731 INT XLeft,
732 INT YLeft,
733 INT Width,
734 INT Height,
735 DWORD dwRop,
736 PBRUSH pbrush)
737 {
738 RECTL DestRect;
739 SURFACE *psurf;
740 EBRUSHOBJ eboFill ;
741 POINTL BrushOrigin;
742 BOOL ret;
743
744 ASSERT(pbrush);
745
746 FIXUP_ROP(dwRop);
747
748 if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
749 {
750 return TRUE;
751 }
752
753 if (Width > 0)
754 {
755 DestRect.left = XLeft;
756 DestRect.right = XLeft + Width;
757 }
758 else
759 {
760 DestRect.left = XLeft + Width + 1;
761 DestRect.right = XLeft + 1;
762 }
763
764 if (Height > 0)
765 {
766 DestRect.top = YLeft;
767 DestRect.bottom = YLeft + Height;
768 }
769 else
770 {
771 DestRect.top = YLeft + Height + 1;
772 DestRect.bottom = YLeft + 1;
773 }
774
775 IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);
776
777 DestRect.left += pdc->ptlDCOrig.x;
778 DestRect.top += pdc->ptlDCOrig.y;
779 DestRect.right += pdc->ptlDCOrig.x;
780 DestRect.bottom += pdc->ptlDCOrig.y;
781 #ifdef _USE_DIBLIB_
782 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft;
783 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft;
784 #else
785 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
786 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
787 #endif
788
789 DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
790
791 psurf = pdc->dclevel.pSurface;
792
793 if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
794 DC_vUpdateFillBrush(pdc);
795
796 EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
797
798 ret = IntEngBitBlt(
799 &psurf->SurfObj,
800 NULL,
801 NULL,
802 pdc->rosdc.CombinedClip,
803 NULL,
804 &DestRect,
805 NULL,
806 NULL,
807 &eboFill.BrushObject,
808 &BrushOrigin,
809 ROP_TO_ROP4(dwRop));
810
811 DC_vFinishBlit(pdc, NULL);
812
813 EBRUSHOBJ_vCleanup(&eboFill);
814
815 return ret;
816 }
817
818 BOOL FASTCALL
819 IntGdiPolyPatBlt(
820 HDC hDC,
821 DWORD dwRop,
822 PPATRECT pRects,
823 INT cRects,
824 ULONG Reserved)
825 {
826 INT i;
827 PBRUSH pbrush;
828 PDC pdc;
829
830 pdc = DC_LockDc(hDC);
831 if (!pdc)
832 {
833 EngSetLastError(ERROR_INVALID_HANDLE);
834 return FALSE;
835 }
836
837 if (pdc->dctype == DC_TYPE_INFO)
838 {
839 DC_UnlockDc(pdc);
840 /* Yes, Windows really returns TRUE in this case */
841 return TRUE;
842 }
843
844 for (i = 0; i < cRects; i++)
845 {
846 pbrush = BRUSH_ShareLockBrush(pRects->hBrush);
847 if(pbrush != NULL)
848 {
849 IntPatBlt(
850 pdc,
851 pRects->r.left,
852 pRects->r.top,
853 pRects->r.right,
854 pRects->r.bottom,
855 dwRop,
856 pbrush);
857 BRUSH_ShareUnlockBrush(pbrush);
858 }
859 pRects++;
860 }
861
862 DC_UnlockDc(pdc);
863
864 return TRUE;
865 }
866
867 BOOL APIENTRY
868 NtGdiPatBlt(
869 HDC hDC,
870 INT XLeft,
871 INT YLeft,
872 INT Width,
873 INT Height,
874 DWORD ROP)
875 {
876 PBRUSH pbrush;
877 DC *dc;
878 PDC_ATTR pdcattr;
879 BOOL ret;
880
881 BOOL UsesSource = ROP_USES_SOURCE(ROP);
882 if (UsesSource)
883 {
884 /* In this case we call on GdiMaskBlt */
885 return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0);
886 }
887
888 dc = DC_LockDc(hDC);
889 if (dc == NULL)
890 {
891 EngSetLastError(ERROR_INVALID_HANDLE);
892 return FALSE;
893 }
894 if (dc->dctype == DC_TYPE_INFO)
895 {
896 DC_UnlockDc(dc);
897 DPRINT1("NtGdiPatBlt on info DC!\n");
898 /* Yes, Windows really returns TRUE in this case */
899 return TRUE;
900 }
901
902 pdcattr = dc->pdcattr;
903
904 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
905 DC_vUpdateFillBrush(dc);
906
907 pbrush = BRUSH_ShareLockBrush(pdcattr->hbrush);
908 if (pbrush == NULL)
909 {
910 EngSetLastError(ERROR_INVALID_HANDLE);
911 DC_UnlockDc(dc);
912 return FALSE;
913 }
914
915 ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush);
916
917 BRUSH_ShareUnlockBrush(pbrush);
918 DC_UnlockDc(dc);
919
920 return ret;
921 }
922
923 BOOL APIENTRY
924 NtGdiPolyPatBlt(
925 HDC hDC,
926 DWORD dwRop,
927 IN PPOLYPATBLT pRects,
928 IN DWORD cRects,
929 IN DWORD Mode)
930 {
931 PPATRECT rb = NULL;
932 NTSTATUS Status = STATUS_SUCCESS;
933 BOOL Ret;
934
935 if (cRects > 0)
936 {
937 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, GDITAG_PLGBLT_DATA);
938 if (!rb)
939 {
940 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
941 return FALSE;
942 }
943 _SEH2_TRY
944 {
945 ProbeForRead(pRects,
946 cRects * sizeof(PATRECT),
947 1);
948 RtlCopyMemory(rb,
949 pRects,
950 cRects * sizeof(PATRECT));
951 }
952 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
953 {
954 Status = _SEH2_GetExceptionCode();
955 }
956 _SEH2_END;
957
958 if (!NT_SUCCESS(Status))
959 {
960 ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA);
961 SetLastNtError(Status);
962 return FALSE;
963 }
964 }
965
966 Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode);
967
968 if (cRects > 0)
969 ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA);
970
971 return Ret;
972 }