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