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