66c387a9f2d851732f4de0f7a5c2624e50fca6ad
[reactos.git] / reactos / win32ss / gdi / ntgdi / bitblt.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 ULONG
21 TranslateCOLORREF(PDC pdc, COLORREF crColor)
22 {
23 PPALETTE ppalDC, ppalSurface;
24 ULONG index, ulColor, iBitmapFormat;
25 EXLATEOBJ exlo;
26
27 switch (crColor >> 24)
28 {
29 case 0x00: /* RGB color */
30 break;
31
32 case 0x01: /* PALETTEINDEX */
33 index = crColor & 0xFFFFFF;
34 ppalDC = pdc->dclevel.ppal;
35 if (index >= ppalDC->NumColors) index = 0;
36
37 /* Get the RGB value */
38 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
39 break;
40
41 case 0x02: /* PALETTERGB */
42
43 if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
44 {
45 /* First find the nearest index in the dc palette */
46 ppalDC = pdc->dclevel.ppal;
47 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
48
49 /* Get the RGB value */
50 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
51 }
52 else
53 {
54 /* Use the pure color */
55 crColor = crColor & 0x00FFFFFF;
56 }
57 break;
58
59 case 0x10: /* DIBINDEX */
60 /* Mask the value to match the target bpp */
61 iBitmapFormat = pdc->dclevel.pSurface->SurfObj.iBitmapFormat;
62 if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
63 else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
64 else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
65 else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
66 else index = crColor & 0xFFFFFF;
67 return index;
68
69 default:
70 DPRINT("Unsupported color type %d passed\n", crColor >> 24);
71 crColor &= 0xFFFFFF;
72 }
73
74 /* Initialize an XLATEOBJ from RGB to the target surface */
75 ppalSurface = pdc->dclevel.pSurface->ppal;
76 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppalSurface, 0xFFFFFF, 0, 0);
77
78 /* Translate the color to the target format */
79 ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
80
81 /* Cleanup the XLATEOBJ */
82 EXLATEOBJ_vCleanup(&exlo);
83
84 return ulColor;
85 }
86
87
88 BOOL APIENTRY
89 NtGdiAlphaBlend(
90 HDC hDCDest,
91 LONG XOriginDest,
92 LONG YOriginDest,
93 LONG WidthDest,
94 LONG HeightDest,
95 HDC hDCSrc,
96 LONG XOriginSrc,
97 LONG YOriginSrc,
98 LONG WidthSrc,
99 LONG HeightSrc,
100 BLENDFUNCTION BlendFunc,
101 HANDLE hcmXform)
102 {
103 PDC DCDest;
104 PDC DCSrc;
105 HDC ahDC[2];
106 PGDIOBJ apObj[2];
107 SURFACE *BitmapDest, *BitmapSrc;
108 RECTL DestRect, SourceRect;
109 BOOL bResult;
110 EXLATEOBJ exlo;
111 BLENDOBJ BlendObj;
112 BlendObj.BlendFunction = BlendFunc;
113
114 if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0)
115 {
116 EngSetLastError(ERROR_INVALID_PARAMETER);
117 return FALSE;
118 }
119
120 DPRINT("Locking DCs\n");
121 ahDC[0] = hDCDest;
122 ahDC[1] = hDCSrc ;
123 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
124 {
125 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
126 EngSetLastError(ERROR_INVALID_HANDLE);
127 return FALSE;
128 }
129 DCDest = apObj[0];
130 DCSrc = apObj[1];
131
132 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
133 {
134 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
135 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
136 /* Yes, Windows really returns TRUE in this case */
137 return TRUE;
138 }
139
140 DestRect.left = XOriginDest;
141 DestRect.top = YOriginDest;
142 DestRect.right = XOriginDest + WidthDest;
143 DestRect.bottom = YOriginDest + HeightDest;
144 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
145
146 DestRect.left += DCDest->ptlDCOrig.x;
147 DestRect.top += DCDest->ptlDCOrig.y;
148 DestRect.right += DCDest->ptlDCOrig.x;
149 DestRect.bottom += DCDest->ptlDCOrig.y;
150
151 SourceRect.left = XOriginSrc;
152 SourceRect.top = YOriginSrc;
153 SourceRect.right = XOriginSrc + WidthSrc;
154 SourceRect.bottom = YOriginSrc + HeightSrc;
155 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
156
157 SourceRect.left += DCSrc->ptlDCOrig.x;
158 SourceRect.top += DCSrc->ptlDCOrig.y;
159 SourceRect.right += DCSrc->ptlDCOrig.x;
160 SourceRect.bottom += DCSrc->ptlDCOrig.y;
161
162 if (!DestRect.right ||
163 !DestRect.bottom ||
164 !SourceRect.right ||
165 !SourceRect.bottom)
166 {
167 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
168 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
169 return TRUE;
170 }
171
172 /* Prepare DCs for blit */
173 DPRINT("Preparing DCs for blit\n");
174 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
175
176 /* Determine surfaces to be used in the bitblt */
177 BitmapDest = DCDest->dclevel.pSurface;
178 if (!BitmapDest)
179 {
180 bResult = FALSE ;
181 goto leave ;
182 }
183
184 BitmapSrc = DCSrc->dclevel.pSurface;
185 if (!BitmapSrc)
186 {
187 bResult = FALSE;
188 goto leave;
189 }
190
191 /* Create the XLATEOBJ. */
192 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
193
194 /* Perform the alpha blend operation */
195 DPRINT("Performing the alpha blend\n");
196 bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
197 &BitmapSrc->SurfObj,
198 DCDest->rosdc.CombinedClip,
199 &exlo.xlo,
200 &DestRect,
201 &SourceRect,
202 &BlendObj);
203
204 EXLATEOBJ_vCleanup(&exlo);
205 leave :
206 DPRINT("Finishing blit\n");
207 DC_vFinishBlit(DCDest, DCSrc);
208 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
209 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
210
211 return bResult;
212 }
213
214 BOOL APIENTRY
215 NtGdiBitBlt(
216 HDC hDCDest,
217 INT XDest,
218 INT YDest,
219 INT Width,
220 INT Height,
221 HDC hDCSrc,
222 INT XSrc,
223 INT YSrc,
224 DWORD ROP,
225 IN DWORD crBackColor,
226 IN FLONG fl)
227 {
228 /* Forward to NtGdiMaskBlt */
229 // TODO: What's fl for?
230 return NtGdiMaskBlt(hDCDest,
231 XDest,
232 YDest,
233 Width,
234 Height,
235 hDCSrc,
236 XSrc,
237 YSrc,
238 NULL,
239 0,
240 0,
241 ROP,
242 crBackColor);
243 }
244
245 BOOL APIENTRY
246 NtGdiTransparentBlt(
247 HDC hdcDst,
248 INT xDst,
249 INT yDst,
250 INT cxDst,
251 INT cyDst,
252 HDC hdcSrc,
253 INT xSrc,
254 INT ySrc,
255 INT cxSrc,
256 INT cySrc,
257 COLORREF TransColor)
258 {
259 PDC DCDest, DCSrc;
260 HDC ahDC[2];
261 PGDIOBJ apObj[2];
262 RECTL rcDest, rcSrc;
263 SURFACE *BitmapDest, *BitmapSrc = NULL;
264 ULONG TransparentColor = 0;
265 BOOL Ret = FALSE;
266 EXLATEOBJ exlo;
267
268 DPRINT("Locking DCs\n");
269 ahDC[0] = hdcDst;
270 ahDC[1] = hdcSrc ;
271 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
272 {
273 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
274 EngSetLastError(ERROR_INVALID_HANDLE);
275 return FALSE;
276 }
277 DCDest = apObj[0];
278 DCSrc = apObj[1];
279
280 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
281 {
282 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
283 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
284 /* Yes, Windows really returns TRUE in this case */
285 return TRUE;
286 }
287
288 rcDest.left = xDst;
289 rcDest.top = yDst;
290 rcDest.right = rcDest.left + cxDst;
291 rcDest.bottom = rcDest.top + cyDst;
292 IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2);
293
294 rcDest.left += DCDest->ptlDCOrig.x;
295 rcDest.top += DCDest->ptlDCOrig.y;
296 rcDest.right += DCDest->ptlDCOrig.x;
297 rcDest.bottom += DCDest->ptlDCOrig.y;
298
299 rcSrc.left = xSrc;
300 rcSrc.top = ySrc;
301 rcSrc.right = rcSrc.left + cxSrc;
302 rcSrc.bottom = rcSrc.top + cySrc;
303 IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2);
304
305 rcSrc.left += DCSrc->ptlDCOrig.x;
306 rcSrc.top += DCSrc->ptlDCOrig.y;
307 rcSrc.right += DCSrc->ptlDCOrig.x;
308 rcSrc.bottom += DCSrc->ptlDCOrig.y;
309
310 /* Prepare for blit */
311 DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
312
313 BitmapDest = DCDest->dclevel.pSurface;
314 if (!BitmapDest)
315 {
316 goto done;
317 }
318
319 BitmapSrc = DCSrc->dclevel.pSurface;
320 if (!BitmapSrc)
321 {
322 goto done;
323 }
324
325 /* Translate Transparent (RGB) Color to the source palette */
326 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0);
327 TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
328 EXLATEOBJ_vCleanup(&exlo);
329
330 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
331
332 Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
333 DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
334 TransparentColor, 0);
335
336 EXLATEOBJ_vCleanup(&exlo);
337
338 done:
339 DC_vFinishBlit(DCDest, DCSrc);
340 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
341 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
342
343 return Ret;
344 }
345
346 BOOL APIENTRY
347 NtGdiMaskBlt(
348 HDC hdcDest,
349 INT nXDest,
350 INT nYDest,
351 INT nWidth,
352 INT nHeight,
353 HDC hdcSrc,
354 INT nXSrc,
355 INT nYSrc,
356 HBITMAP hbmMask,
357 INT xMask,
358 INT yMask,
359 DWORD dwRop,
360 IN DWORD crBackColor)
361 {
362 PDC DCDest;
363 PDC DCSrc = NULL;
364 HDC ahDC[2];
365 PGDIOBJ apObj[2];
366 PDC_ATTR pdcattr = NULL;
367 SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL;
368 RECTL DestRect, SourceRect;
369 POINTL SourcePoint, MaskPoint;
370 BOOL Status = FALSE;
371 EXLATEOBJ exlo;
372 XLATEOBJ *XlateObj = NULL;
373 BOOL UsesSource = ROP_USES_SOURCE(dwRop);
374 BOOL UsesMask;
375
376 FIXUP_ROP(dwRop);
377
378 UsesMask = ROP_USES_MASK(dwRop);
379
380 //DPRINT1("dwRop : 0x%08x\n", dwRop);
381 if (!hdcDest || (UsesSource && !hdcSrc))
382 {
383 EngSetLastError(ERROR_INVALID_PARAMETER);
384 return FALSE;
385 }
386
387 /* Take care of mask bitmap */
388 if(hbmMask)
389 {
390 psurfMask = SURFACE_ShareLockSurface(hbmMask);
391 if(!psurfMask)
392 {
393 EngSetLastError(ERROR_INVALID_HANDLE);
394 return FALSE;
395 }
396 }
397
398 if(UsesMask)
399 {
400 if(!psurfMask)
401 {
402 EngSetLastError(ERROR_INVALID_PARAMETER);
403 return FALSE;
404 }
405 if(gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1)
406 {
407 EngSetLastError(ERROR_INVALID_PARAMETER);
408 SURFACE_ShareUnlockSurface(psurfMask);
409 return FALSE;
410 }
411 }
412 else if(psurfMask)
413 {
414 DPRINT1("Getting Mask bitmap without needing it?\n");
415 SURFACE_ShareUnlockSurface(psurfMask);
416 psurfMask = NULL;
417 }
418 MaskPoint.x = xMask;
419 MaskPoint.y = yMask;
420
421 /* Take care of source and destination bitmap */
422 DPRINT("Locking DCs\n");
423 ahDC[0] = hdcDest;
424 ahDC[1] = UsesSource ? hdcSrc : NULL;
425 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
426 {
427 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
428 EngSetLastError(ERROR_INVALID_HANDLE);
429 return FALSE;
430 }
431 DCDest = apObj[0];
432 DCSrc = apObj[1];
433
434 ASSERT(DCDest);
435 if (NULL == DCDest)
436 {
437 if(DCSrc) DC_UnlockDc(DCSrc);
438 DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcDest);
439 return FALSE;
440 }
441
442 if (DCDest->dctype == DC_TYPE_INFO)
443 {
444 if(DCSrc) DC_UnlockDc(DCSrc);
445 DC_UnlockDc(DCDest);
446 /* Yes, Windows really returns TRUE in this case */
447 return TRUE;
448 }
449
450 if (UsesSource)
451 {
452 ASSERT(DCSrc);
453 if (DCSrc->dctype == DC_TYPE_INFO)
454 {
455 DC_UnlockDc(DCDest);
456 DC_UnlockDc(DCSrc);
457 /* Yes, Windows really returns TRUE in this case */
458 return TRUE;
459 }
460 }
461
462 pdcattr = DCDest->pdcattr;
463
464 DestRect.left = nXDest;
465 DestRect.top = nYDest;
466 DestRect.right = nXDest + nWidth;
467 DestRect.bottom = nYDest + nHeight;
468 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
469
470 DestRect.left += DCDest->ptlDCOrig.x;
471 DestRect.top += DCDest->ptlDCOrig.y;
472 DestRect.right += DCDest->ptlDCOrig.x;
473 DestRect.bottom += DCDest->ptlDCOrig.y;
474
475 SourcePoint.x = nXSrc;
476 SourcePoint.y = nYSrc;
477
478 if (UsesSource)
479 {
480 IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);
481
482 SourcePoint.x += DCSrc->ptlDCOrig.x;
483 SourcePoint.y += DCSrc->ptlDCOrig.y;
484 /* Calculate Source Rect */
485 SourceRect.left = SourcePoint.x;
486 SourceRect.top = SourcePoint.y;
487 SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
488 SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
489 }
490
491 /* Prepare blit */
492 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
493
494 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
495 DC_vUpdateFillBrush(DCDest);
496
497 /* Determine surfaces to be used in the bitblt */
498 BitmapDest = DCDest->dclevel.pSurface;
499 if (!BitmapDest)
500 goto cleanup;
501
502 if (UsesSource)
503 {
504 {
505 BitmapSrc = DCSrc->dclevel.pSurface;
506 if (!BitmapSrc)
507 goto cleanup;
508 }
509 }
510
511 /* Create the XLATEOBJ. */
512 if (UsesSource)
513 {
514 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
515 XlateObj = &exlo.xlo;
516 }
517
518
519 /* Perform the bitblt operation */
520 Status = IntEngBitBlt(&BitmapDest->SurfObj,
521 BitmapSrc ? &BitmapSrc->SurfObj : NULL,
522 psurfMask ? &psurfMask->SurfObj : NULL,
523 DCDest->rosdc.CombinedClip,
524 XlateObj,
525 &DestRect,
526 &SourcePoint,
527 &MaskPoint,
528 &DCDest->eboFill.BrushObject,
529 &DCDest->dclevel.pbrFill->ptOrigin,
530 ROP_TO_ROP4(dwRop));
531
532 if (UsesSource)
533 EXLATEOBJ_vCleanup(&exlo);
534 cleanup:
535 DC_vFinishBlit(DCDest, DCSrc);
536 if (UsesSource)
537 {
538 DC_UnlockDc(DCSrc);
539 }
540 DC_UnlockDc(DCDest);
541 if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
542
543 return Status;
544 }
545
546 BOOL
547 APIENTRY
548 NtGdiPlgBlt(
549 IN HDC hdcTrg,
550 IN LPPOINT pptlTrg,
551 IN HDC hdcSrc,
552 IN INT xSrc,
553 IN INT ySrc,
554 IN INT cxSrc,
555 IN INT cySrc,
556 IN HBITMAP hbmMask,
557 IN INT xMask,
558 IN INT yMask,
559 IN DWORD crBackColor)
560 {
561 UNIMPLEMENTED;
562 return FALSE;
563 }
564
565 BOOL APIENTRY
566 GreStretchBltMask(
567 HDC hDCDest,
568 INT XOriginDest,
569 INT YOriginDest,
570 INT WidthDest,
571 INT HeightDest,
572 HDC hDCSrc,
573 INT XOriginSrc,
574 INT YOriginSrc,
575 INT WidthSrc,
576 INT HeightSrc,
577 DWORD ROP,
578 IN DWORD dwBackColor,
579 HDC hDCMask,
580 INT XOriginMask,
581 INT YOriginMask)
582 {
583 PDC DCDest;
584 PDC DCSrc = NULL;
585 PDC DCMask = NULL;
586 HDC ahDC[3];
587 PGDIOBJ apObj[3];
588 PDC_ATTR pdcattr;
589 SURFACE *BitmapDest, *BitmapSrc = NULL;
590 SURFACE *BitmapMask = NULL;
591 RECTL DestRect;
592 RECTL SourceRect;
593 POINTL MaskPoint;
594 BOOL Status = FALSE;
595 EXLATEOBJ exlo;
596 XLATEOBJ *XlateObj = NULL;
597 POINTL BrushOrigin;
598 BOOL UsesSource;
599 BOOL UsesMask;
600
601 FIXUP_ROP(ROP);
602 UsesSource = ROP_USES_SOURCE(ROP);
603 UsesMask = ROP_USES_MASK(ROP);
604
605 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
606 {
607 EngSetLastError(ERROR_INVALID_PARAMETER);
608 return TRUE;
609 }
610
611 if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask))
612 {
613 EngSetLastError(ERROR_INVALID_PARAMETER);
614 return FALSE;
615 }
616
617 ahDC[0] = hDCDest;
618 ahDC[1] = UsesSource ? hDCSrc : NULL;
619 ahDC[2] = UsesMask ? hDCMask : NULL;
620 if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
621 {
622 DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
623 EngSetLastError(ERROR_INVALID_HANDLE);
624 return FALSE;
625 }
626 DCDest = apObj[0];
627 DCSrc = apObj[1];
628 DCMask = apObj[2];
629
630 if (DCDest->dctype == DC_TYPE_INFO)
631 {
632 if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
633 if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
634 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
635 /* Yes, Windows really returns TRUE in this case */
636 return TRUE;
637 }
638
639 if (UsesSource)
640 {
641 if (DCSrc->dctype == DC_TYPE_INFO)
642 {
643 GDIOBJ_vUnlockObject(&DCDest->BaseObject);
644 GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
645 if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
646 /* Yes, Windows really returns TRUE in this case */
647 return TRUE;
648 }
649 }
650
651 pdcattr = DCDest->pdcattr;
652
653 DestRect.left = XOriginDest;
654 DestRect.top = YOriginDest;
655 DestRect.right = XOriginDest+WidthDest;
656 DestRect.bottom = YOriginDest+HeightDest;
657 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
658
659 DestRect.left += DCDest->ptlDCOrig.x;
660 DestRect.top += DCDest->ptlDCOrig.y;
661 DestRect.right += DCDest->ptlDCOrig.x;
662 DestRect.bottom += DCDest->ptlDCOrig.y;
663
664 SourceRect.left = XOriginSrc;
665 SourceRect.top = YOriginSrc;
666 SourceRect.right = XOriginSrc+WidthSrc;
667 SourceRect.bottom = YOriginSrc+HeightSrc;
668
669 if (UsesSource)
670 {
671 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
672
673 SourceRect.left += DCSrc->ptlDCOrig.x;
674 SourceRect.top += DCSrc->ptlDCOrig.y;
675 SourceRect.right += DCSrc->ptlDCOrig.x;
676 SourceRect.bottom += DCSrc->ptlDCOrig.y;
677 }
678
679 BrushOrigin.x = 0;
680 BrushOrigin.y = 0;
681
682 /* Only prepare Source and Dest, hdcMask represents a DIB */
683 DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
684
685 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
686 DC_vUpdateFillBrush(DCDest);
687
688 /* Determine surfaces to be used in the bitblt */
689 BitmapDest = DCDest->dclevel.pSurface;
690 if (BitmapDest == NULL)
691 goto failed;
692 if (UsesSource)
693 {
694 BitmapSrc = DCSrc->dclevel.pSurface;
695 if (BitmapSrc == NULL)
696 goto failed;
697
698 /* Create the XLATEOBJ. */
699 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
700 XlateObj = &exlo.xlo;
701 }
702
703 /* Offset the brush */
704 BrushOrigin.x += DCDest->ptlDCOrig.x;
705 BrushOrigin.y += DCDest->ptlDCOrig.y;
706
707 /* Make mask surface for source surface */
708 if (BitmapSrc && DCMask)
709 {
710 BitmapMask = DCMask->dclevel.pSurface;
711 if (BitmapMask &&
712 (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
713 BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
714 {
715 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
716 BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
717 WidthSrc, HeightSrc);
718 EXLATEOBJ_vCleanup(&exlo);
719 goto failed;
720 }
721 /* Create mask offset point */
722 MaskPoint.x = XOriginMask;
723 MaskPoint.y = YOriginMask;
724 IntLPtoDP(DCMask, &MaskPoint, 1);
725 MaskPoint.x += DCMask->ptlDCOrig.x;
726 MaskPoint.y += DCMask->ptlDCOrig.y;
727 }
728
729 /* Perform the bitblt operation */
730 Status = IntEngStretchBlt(&BitmapDest->SurfObj,
731 &BitmapSrc->SurfObj,
732 BitmapMask ? &BitmapMask->SurfObj : NULL,
733 DCDest->rosdc.CombinedClip,
734 XlateObj,
735 &DestRect,
736 &SourceRect,
737 BitmapMask ? &MaskPoint : NULL,
738 &DCDest->eboFill.BrushObject,
739 &BrushOrigin,
740 ROP_TO_ROP4(ROP));
741 if (UsesSource)
742 {
743 EXLATEOBJ_vCleanup(&exlo);
744 }
745
746 failed:
747 DC_vFinishBlit(DCDest, DCSrc);
748 if (UsesSource)
749 {
750 DC_UnlockDc(DCSrc);
751 }
752 if (DCMask)
753 {
754 DC_UnlockDc(DCMask);
755 }
756 DC_UnlockDc(DCDest);
757
758 return Status;
759 }
760
761
762 BOOL APIENTRY
763 NtGdiStretchBlt(
764 HDC hDCDest,
765 INT XOriginDest,
766 INT YOriginDest,
767 INT WidthDest,
768 INT HeightDest,
769 HDC hDCSrc,
770 INT XOriginSrc,
771 INT YOriginSrc,
772 INT WidthSrc,
773 INT HeightSrc,
774 DWORD ROP,
775 IN DWORD dwBackColor)
776 {
777 return GreStretchBltMask(
778 hDCDest,
779 XOriginDest,
780 YOriginDest,
781 WidthDest,
782 HeightDest,
783 hDCSrc,
784 XOriginSrc,
785 YOriginSrc,
786 WidthSrc,
787 HeightSrc,
788 ROP,
789 dwBackColor,
790 NULL,
791 0,
792 0);
793 }
794
795
796 BOOL FASTCALL
797 IntPatBlt(
798 PDC pdc,
799 INT XLeft,
800 INT YLeft,
801 INT Width,
802 INT Height,
803 DWORD dwRop,
804 PEBRUSHOBJ pebo)
805 {
806 RECTL DestRect;
807 SURFACE *psurf;
808 POINTL BrushOrigin;
809 BOOL ret;
810 PBRUSH pbrush = pebo->pbrush;
811
812 ASSERT(pebo);
813
814 FIXUP_ROP(dwRop);
815
816 if (pbrush->flAttrs & BR_IS_NULL)
817 {
818 return TRUE;
819 }
820
821 if (Width > 0)
822 {
823 DestRect.left = XLeft;
824 DestRect.right = XLeft + Width;
825 }
826 else
827 {
828 DestRect.left = XLeft + Width + 1;
829 DestRect.right = XLeft + 1;
830 }
831
832 if (Height > 0)
833 {
834 DestRect.top = YLeft;
835 DestRect.bottom = YLeft + Height;
836 }
837 else
838 {
839 DestRect.top = YLeft + Height + 1;
840 DestRect.bottom = YLeft + 1;
841 }
842
843 IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);
844
845 DestRect.left += pdc->ptlDCOrig.x;
846 DestRect.top += pdc->ptlDCOrig.y;
847 DestRect.right += pdc->ptlDCOrig.x;
848 DestRect.bottom += pdc->ptlDCOrig.y;
849 #ifdef _USE_DIBLIB_
850 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft;
851 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft;
852 #else
853 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
854 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
855 #endif
856
857 DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
858
859 psurf = pdc->dclevel.pSurface;
860
861 ret = IntEngBitBlt(
862 &psurf->SurfObj,
863 NULL,
864 NULL,
865 pdc->rosdc.CombinedClip,
866 NULL,
867 &DestRect,
868 NULL,
869 NULL,
870 &pebo->BrushObject,
871 &BrushOrigin,
872 ROP_TO_ROP4(dwRop));
873
874 DC_vFinishBlit(pdc, NULL);
875
876 return ret;
877 }
878
879 BOOL FASTCALL
880 IntGdiPolyPatBlt(
881 HDC hDC,
882 DWORD dwRop,
883 PPATRECT pRects,
884 INT cRects,
885 ULONG Reserved)
886 {
887 INT i;
888 PBRUSH pbrush;
889 PDC pdc;
890 EBRUSHOBJ eboFill;
891
892 pdc = DC_LockDc(hDC);
893 if (!pdc)
894 {
895 EngSetLastError(ERROR_INVALID_HANDLE);
896 return FALSE;
897 }
898
899 if (pdc->dctype == DC_TYPE_INFO)
900 {
901 DC_UnlockDc(pdc);
902 /* Yes, Windows really returns TRUE in this case */
903 return TRUE;
904 }
905
906 for (i = 0; i < cRects; i++)
907 {
908 pbrush = BRUSH_ShareLockBrush(pRects->hBrush);
909
910 /* Check if we could lock the brush */
911 if (pbrush != NULL)
912 {
913 /* Initialize a brush object */
914 EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
915
916 IntPatBlt(
917 pdc,
918 pRects->r.left,
919 pRects->r.top,
920 pRects->r.right,
921 pRects->r.bottom,
922 dwRop,
923 &eboFill);
924
925 /* Cleanup the brush object and unlock the brush */
926 EBRUSHOBJ_vCleanup(&eboFill);
927 BRUSH_ShareUnlockBrush(pbrush);
928 }
929 pRects++;
930 }
931
932 DC_UnlockDc(pdc);
933
934 return TRUE;
935 }
936
937 BOOL
938 APIENTRY
939 NtGdiPatBlt(
940 _In_ HDC hdcDest,
941 _In_ INT x,
942 _In_ INT y,
943 _In_ INT cx,
944 _In_ INT cy,
945 _In_ DWORD dwRop)
946 {
947 BOOL bResult;
948 PDC pdc;
949
950 /* Mask away everything except foreground rop index */
951 dwRop = dwRop & 0x00FF0000;
952 dwRop |= dwRop << 8;
953
954 /* Check if the rop uses a source */
955 if (ROP_USES_SOURCE(dwRop))
956 {
957 /* This is not possible */
958 return 0;
959 }
960
961 /* Lock the DC */
962 pdc = DC_LockDc(hdcDest);
963 if (pdc == NULL)
964 {
965 EngSetLastError(ERROR_INVALID_HANDLE);
966 return FALSE;
967 }
968
969 /* Check if the DC has no surface (empty mem or info DC) */
970 if (pdc->dclevel.pSurface == NULL)
971 {
972 /* Nothing to do, Windows returns TRUE! */
973 DC_UnlockDc(pdc);
974 return TRUE;
975 }
976
977 /* Update the fill brush, if neccessary */
978 if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
979 DC_vUpdateFillBrush(pdc);
980
981 /* Call the internal function */
982 bResult = IntPatBlt(pdc, x, y, cx, cy, dwRop, &pdc->eboFill);
983
984 /* Unlock the DC and return the result */
985 DC_UnlockDc(pdc);
986 return bResult;
987 }
988
989 BOOL
990 APIENTRY
991 NtGdiPolyPatBlt(
992 HDC hDC,
993 DWORD dwRop,
994 IN PPOLYPATBLT pRects,
995 IN DWORD cRects,
996 IN DWORD Mode)
997 {
998 PPATRECT rb = NULL;
999 NTSTATUS Status = STATUS_SUCCESS;
1000 BOOL Ret;
1001
1002 if (cRects > 0)
1003 {
1004 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, GDITAG_PLGBLT_DATA);
1005 if (!rb)
1006 {
1007 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1008 return FALSE;
1009 }
1010 _SEH2_TRY
1011 {
1012 ProbeForRead(pRects,
1013 cRects * sizeof(PATRECT),
1014 1);
1015 RtlCopyMemory(rb,
1016 pRects,
1017 cRects * sizeof(PATRECT));
1018 }
1019 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1020 {
1021 Status = _SEH2_GetExceptionCode();
1022 }
1023 _SEH2_END;
1024
1025 if (!NT_SUCCESS(Status))
1026 {
1027 ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA);
1028 SetLastNtError(Status);
1029 return FALSE;
1030 }
1031 }
1032
1033 Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode);
1034
1035 if (cRects > 0)
1036 ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA);
1037
1038 return Ret;
1039 }
1040
1041
1042 COLORREF
1043 APIENTRY
1044 NtGdiSetPixel(
1045 _In_ HDC hdc,
1046 _In_ INT x,
1047 _In_ INT y,
1048 _In_ COLORREF crColor)
1049 {
1050 PDC pdc;
1051 ULONG iOldColor, iSolidColor;
1052 BOOL bResult;
1053 PEBRUSHOBJ pebo;
1054 ULONG ulDirty;
1055 EXLATEOBJ exlo;
1056
1057 /* Lock the DC */
1058 pdc = DC_LockDc(hdc);
1059 if (!pdc)
1060 {
1061 EngSetLastError(ERROR_INVALID_HANDLE);
1062 return -1;
1063 }
1064
1065 /* Check if the DC has no surface (empty mem or info DC) */
1066 if (pdc->dclevel.pSurface == NULL)
1067 {
1068 /* Fail! */
1069 DC_UnlockDc(pdc);
1070 return -1;
1071 }
1072
1073 /* Translate the color to the target format and get the RGB value */
1074 iSolidColor = TranslateCOLORREF(pdc, crColor);
1075
1076 /* Use the DC's text brush, which is always a solid brush */
1077 pebo = &pdc->eboText;
1078
1079 /* Save the old solid color and set the one for the pixel */
1080 iOldColor = EBRUSHOBJ_iSetSolidColor(pebo, iSolidColor);
1081
1082 /* Save dirty flags and reset dirty text brush flag */
1083 ulDirty = pdc->pdcattr->ulDirty_;
1084 pdc->pdcattr->ulDirty_ &= ~DIRTY_TEXT;
1085
1086 /* Call the internal function */
1087 bResult = IntPatBlt(pdc, x, y, 1, 1, PATCOPY, pebo);
1088
1089 /* Restore old text brush color and dirty flags */
1090 EBRUSHOBJ_iSetSolidColor(pebo, iOldColor);
1091 pdc->pdcattr->ulDirty_ = ulDirty;
1092
1093 /* Initialize an XLATEOBJ from the target surface to RGB */
1094 EXLATEOBJ_vInitialize(&exlo,
1095 pdc->dclevel.pSurface->ppal,
1096 &gpalRGB,
1097 0,
1098 pdc->pdcattr->crBackgroundClr,
1099 pdc->pdcattr->crForegroundClr);
1100
1101 /* Translate the color back to RGB */
1102 crColor = XLATEOBJ_iXlate(&exlo.xlo, iSolidColor);
1103
1104 /* Cleanup and return the target format color */
1105 EXLATEOBJ_vCleanup(&exlo);
1106
1107 /* Unlock the DC */
1108 DC_UnlockDc(pdc);
1109
1110 /* Return the new RGB color or -1 on failure */
1111 return bResult ? crColor : -1;
1112 }
1113
1114 COLORREF
1115 APIENTRY
1116 NtGdiGetPixel(
1117 _In_ HDC hdc,
1118 _In_ INT x,
1119 _In_ INT y)
1120 {
1121 PDC pdc;
1122 ULONG ulRGBColor = CLR_INVALID;
1123 POINTL ptlSrc;
1124 PSURFACE psurfSrc, psurfDest;
1125
1126 /* Lock the DC */
1127 pdc = DC_LockDc(hdc);
1128 if (!pdc)
1129 {
1130 EngSetLastError(ERROR_INVALID_HANDLE);
1131 return CLR_INVALID;
1132 }
1133
1134 /* Check if the DC has no surface (empty mem or info DC) */
1135 psurfSrc = pdc->dclevel.pSurface;
1136 if (psurfSrc == NULL)
1137 {
1138 /* Fail! */
1139 goto leave;
1140 }
1141
1142 /* Get the logical coordinates */
1143 ptlSrc.x = x;
1144 ptlSrc.y = y;
1145
1146 /* Translate coordinates to device coordinates */
1147 IntLPtoDP(pdc, &ptlSrc, 1);
1148 ptlSrc.x += pdc->ptlDCOrig.x;
1149 ptlSrc.y += pdc->ptlDCOrig.y;
1150
1151 /* Check if the pixel is outside the surface */
1152 if ((ptlSrc.x >= psurfSrc->SurfObj.sizlBitmap.cx) ||
1153 (ptlSrc.y >= psurfSrc->SurfObj.sizlBitmap.cy))
1154 {
1155 /* Fail! */
1156 goto leave;
1157 }
1158
1159 /* Allocate a surface */
1160 psurfDest = SURFACE_AllocSurface(STYPE_BITMAP,
1161 1,
1162 1,
1163 BMF_32BPP,
1164 0,
1165 0,
1166 &ulRGBColor);
1167 if (psurfDest)
1168 {
1169 RECTL rclDest = {0, 0, 1, 1};
1170 EXLATEOBJ exlo;
1171
1172 /* Translate from the source palette to RGB color */
1173 EXLATEOBJ_vInitialize(&exlo,
1174 psurfSrc->ppal,
1175 &gpalRGB,
1176 0,
1177 RGB(0xff,0xff,0xff),
1178 RGB(0,0,0));
1179
1180 /* Call the copy bits function */
1181 EngCopyBits(&psurfDest->SurfObj,
1182 &psurfSrc->SurfObj,
1183 NULL,
1184 &exlo.xlo,
1185 &rclDest,
1186 &ptlSrc);
1187
1188 /* Cleanup the XLATEOBJ */
1189 EXLATEOBJ_vCleanup(&exlo);
1190
1191 /* Delete the surface */
1192 GDIOBJ_vDeleteObject(&psurfDest->BaseObject);
1193 }
1194
1195 leave:
1196 /* Unlock the DC */
1197 DC_UnlockDc(pdc);
1198
1199 /* Return the new RGB color or -1 on failure */
1200 return ulRGBColor;
1201 }
1202