1 /* 2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Bit blit functions 5 * FILE: win32ss/gdi/ntgdi/bitblt.c 6 * PROGRAMER: Unknown 7 */ 8 9 #include <win32k.h> 10 DBG_DEFAULT_CHANNEL(GdiBlt); 11 12 BOOL APIENTRY 13 NtGdiAlphaBlend( 14 HDC hDCDest, 15 LONG XOriginDest, 16 LONG YOriginDest, 17 LONG WidthDest, 18 LONG HeightDest, 19 HDC hDCSrc, 20 LONG XOriginSrc, 21 LONG YOriginSrc, 22 LONG WidthSrc, 23 LONG HeightSrc, 24 BLENDFUNCTION BlendFunc, 25 HANDLE hcmXform) 26 { 27 PDC DCDest; 28 PDC DCSrc; 29 HDC ahDC[2]; 30 PGDIOBJ apObj[2]; 31 SURFACE *BitmapDest, *BitmapSrc; 32 RECTL DestRect, SourceRect; 33 BOOL bResult; 34 EXLATEOBJ exlo; 35 BLENDOBJ BlendObj; 36 BlendObj.BlendFunction = BlendFunc; 37 38 if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0) 39 { 40 EngSetLastError(ERROR_INVALID_PARAMETER); 41 return FALSE; 42 } 43 44 if ((hDCDest == NULL) || (hDCSrc == NULL)) 45 { 46 EngSetLastError(ERROR_INVALID_PARAMETER); 47 return FALSE; 48 } 49 50 TRACE("Locking DCs\n"); 51 ahDC[0] = hDCDest; 52 ahDC[1] = hDCSrc ; 53 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) 54 { 55 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc); 56 EngSetLastError(ERROR_INVALID_HANDLE); 57 return FALSE; 58 } 59 DCDest = apObj[0]; 60 DCSrc = apObj[1]; 61 62 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) 63 { 64 GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 65 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 66 /* Yes, Windows really returns TRUE in this case */ 67 return TRUE; 68 } 69 70 DestRect.left = XOriginDest; 71 DestRect.top = YOriginDest; 72 DestRect.right = XOriginDest + WidthDest; 73 DestRect.bottom = YOriginDest + HeightDest; 74 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); 75 76 DestRect.left += DCDest->ptlDCOrig.x; 77 DestRect.top += DCDest->ptlDCOrig.y; 78 DestRect.right += DCDest->ptlDCOrig.x; 79 DestRect.bottom += DCDest->ptlDCOrig.y; 80 81 if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 82 { 83 IntUpdateBoundsRect(DCDest, &DestRect); 84 } 85 86 SourceRect.left = XOriginSrc; 87 SourceRect.top = YOriginSrc; 88 SourceRect.right = XOriginSrc + WidthSrc; 89 SourceRect.bottom = YOriginSrc + HeightSrc; 90 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2); 91 92 SourceRect.left += DCSrc->ptlDCOrig.x; 93 SourceRect.top += DCSrc->ptlDCOrig.y; 94 SourceRect.right += DCSrc->ptlDCOrig.x; 95 SourceRect.bottom += DCSrc->ptlDCOrig.y; 96 97 if (!DestRect.right || 98 !DestRect.bottom || 99 !SourceRect.right || 100 !SourceRect.bottom) 101 { 102 GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 103 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 104 return TRUE; 105 } 106 107 /* Prepare DCs for blit */ 108 TRACE("Preparing DCs for blit\n"); 109 DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); 110 111 /* Determine surfaces to be used in the bitblt */ 112 BitmapDest = DCDest->dclevel.pSurface; 113 if (!BitmapDest) 114 { 115 bResult = FALSE ; 116 goto leave ; 117 } 118 119 BitmapSrc = DCSrc->dclevel.pSurface; 120 if (!BitmapSrc) 121 { 122 bResult = FALSE; 123 goto leave; 124 } 125 126 /* Create the XLATEOBJ. */ 127 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); 128 129 /* Perform the alpha blend operation */ 130 TRACE("Performing the alpha blend\n"); 131 bResult = IntEngAlphaBlend(&BitmapDest->SurfObj, 132 &BitmapSrc->SurfObj, 133 (CLIPOBJ *)&DCDest->co, 134 &exlo.xlo, 135 &DestRect, 136 &SourceRect, 137 &BlendObj); 138 139 EXLATEOBJ_vCleanup(&exlo); 140 leave : 141 TRACE("Finishing blit\n"); 142 DC_vFinishBlit(DCDest, DCSrc); 143 GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 144 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 145 146 return bResult; 147 } 148 149 BOOL APIENTRY 150 NtGdiBitBlt( 151 HDC hDCDest, 152 INT XDest, 153 INT YDest, 154 INT Width, 155 INT Height, 156 HDC hDCSrc, 157 INT XSrc, 158 INT YSrc, 159 DWORD dwRop, 160 IN DWORD crBackColor, 161 IN FLONG fl) 162 { 163 164 if (dwRop & CAPTUREBLT) 165 { 166 return NtGdiStretchBlt(hDCDest, 167 XDest, 168 YDest, 169 Width, 170 Height, 171 hDCSrc, 172 XSrc, 173 YSrc, 174 Width, 175 Height, 176 dwRop, 177 crBackColor); 178 } 179 180 dwRop = dwRop & ~(NOMIRRORBITMAP|CAPTUREBLT); 181 182 /* Forward to NtGdiMaskBlt */ 183 // TODO: What's fl for? LOL not to send this to MaskBit! 184 return NtGdiMaskBlt(hDCDest, 185 XDest, 186 YDest, 187 Width, 188 Height, 189 hDCSrc, 190 XSrc, 191 YSrc, 192 NULL, 193 0, 194 0, 195 MAKEROP4(dwRop, dwRop), 196 crBackColor); 197 } 198 199 BOOL APIENTRY 200 NtGdiTransparentBlt( 201 HDC hdcDst, 202 INT xDst, 203 INT yDst, 204 INT cxDst, 205 INT cyDst, 206 HDC hdcSrc, 207 INT xSrc, 208 INT ySrc, 209 INT cxSrc, 210 INT cySrc, 211 COLORREF TransColor) 212 { 213 PDC DCDest, DCSrc; 214 HDC ahDC[2]; 215 PGDIOBJ apObj[2]; 216 RECTL rcDest, rcSrc; 217 SURFACE *BitmapDest, *BitmapSrc = NULL; 218 ULONG TransparentColor = 0; 219 BOOL Ret = FALSE; 220 EXLATEOBJ exlo; 221 222 if ((hdcDst == NULL) || (hdcSrc == NULL)) 223 { 224 EngSetLastError(ERROR_INVALID_PARAMETER); 225 return FALSE; 226 } 227 228 TRACE("Locking DCs\n"); 229 ahDC[0] = hdcDst; 230 ahDC[1] = hdcSrc ; 231 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) 232 { 233 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc); 234 EngSetLastError(ERROR_INVALID_HANDLE); 235 return FALSE; 236 } 237 DCDest = apObj[0]; 238 DCSrc = apObj[1]; 239 240 if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) 241 { 242 GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 243 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 244 /* Yes, Windows really returns TRUE in this case */ 245 return TRUE; 246 } 247 248 rcDest.left = xDst; 249 rcDest.top = yDst; 250 rcDest.right = rcDest.left + cxDst; 251 rcDest.bottom = rcDest.top + cyDst; 252 IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2); 253 254 rcDest.left += DCDest->ptlDCOrig.x; 255 rcDest.top += DCDest->ptlDCOrig.y; 256 rcDest.right += DCDest->ptlDCOrig.x; 257 rcDest.bottom += DCDest->ptlDCOrig.y; 258 259 rcSrc.left = xSrc; 260 rcSrc.top = ySrc; 261 rcSrc.right = rcSrc.left + cxSrc; 262 rcSrc.bottom = rcSrc.top + cySrc; 263 IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2); 264 265 rcSrc.left += DCSrc->ptlDCOrig.x; 266 rcSrc.top += DCSrc->ptlDCOrig.y; 267 rcSrc.right += DCSrc->ptlDCOrig.x; 268 rcSrc.bottom += DCSrc->ptlDCOrig.y; 269 270 if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 271 { 272 IntUpdateBoundsRect(DCDest, &rcDest); 273 } 274 275 /* Prepare for blit */ 276 DC_vPrepareDCsForBlit(DCDest, &rcDest, DCSrc, &rcSrc); 277 278 BitmapDest = DCDest->dclevel.pSurface; 279 if (!BitmapDest) 280 { 281 goto done; 282 } 283 284 BitmapSrc = DCSrc->dclevel.pSurface; 285 if (!BitmapSrc) 286 { 287 goto done; 288 } 289 290 /* Translate Transparent (RGB) Color to the source palette */ 291 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0); 292 TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor); 293 EXLATEOBJ_vCleanup(&exlo); 294 295 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); 296 297 Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, 298 (CLIPOBJ *)&DCDest->co, &exlo.xlo, &rcDest, &rcSrc, 299 TransparentColor, 0); 300 301 EXLATEOBJ_vCleanup(&exlo); 302 303 done: 304 DC_vFinishBlit(DCDest, DCSrc); 305 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 306 GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 307 308 return Ret; 309 } 310 311 BOOL APIENTRY 312 NtGdiMaskBlt( 313 HDC hdcDest, 314 INT nXDest, 315 INT nYDest, 316 INT nWidth, 317 INT nHeight, 318 HDC hdcSrc, 319 INT nXSrc, 320 INT nYSrc, 321 HBITMAP hbmMask, 322 INT xMask, 323 INT yMask, 324 DWORD dwRop4, 325 IN DWORD crBackColor) 326 { 327 PDC DCDest; 328 PDC DCSrc = NULL; 329 HDC ahDC[2]; 330 PGDIOBJ apObj[2]; 331 PDC_ATTR pdcattr = NULL; 332 SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL; 333 RECTL DestRect, SourceRect; 334 POINTL SourcePoint, MaskPoint; 335 BOOL Status = FALSE; 336 EXLATEOBJ exlo; 337 XLATEOBJ *XlateObj = NULL; 338 BOOL UsesSource; 339 ROP4 rop4; 340 341 rop4 = WIN32_ROP4_TO_ENG_ROP4(dwRop4); 342 343 UsesSource = ROP4_USES_SOURCE(rop4); 344 if (!hdcDest || (UsesSource && !hdcSrc)) 345 { 346 EngSetLastError(ERROR_INVALID_PARAMETER); 347 return FALSE; 348 } 349 350 /* Check if we need a mask and have a mask bitmap */ 351 if (ROP4_USES_MASK(rop4) && (hbmMask != NULL)) 352 { 353 /* Reference the mask bitmap */ 354 psurfMask = SURFACE_ShareLockSurface(hbmMask); 355 if (psurfMask == NULL) 356 { 357 EngSetLastError(ERROR_INVALID_HANDLE); 358 return FALSE; 359 } 360 361 /* Make sure the mask bitmap is 1 BPP */ 362 if (gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1) 363 { 364 EngSetLastError(ERROR_INVALID_PARAMETER); 365 SURFACE_ShareUnlockSurface(psurfMask); 366 return FALSE; 367 } 368 } 369 else 370 { 371 /* We use NULL, if we need a mask, the Eng function will take care of 372 that and use the brushobject to get a mask */ 373 psurfMask = NULL; 374 } 375 376 MaskPoint.x = xMask; 377 MaskPoint.y = yMask; 378 379 /* Take care of source and destination bitmap */ 380 TRACE("Locking DCs\n"); 381 ahDC[0] = hdcDest; 382 ahDC[1] = UsesSource ? hdcSrc : NULL; 383 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) 384 { 385 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiMaskBlt\n", hdcDest, hdcSrc); 386 EngSetLastError(ERROR_INVALID_HANDLE); 387 return FALSE; 388 } 389 DCDest = apObj[0]; 390 DCSrc = apObj[1]; 391 392 ASSERT(DCDest); 393 if (NULL == DCDest) 394 { 395 if(DCSrc) DC_UnlockDc(DCSrc); 396 WARN("Invalid destination dc handle (0x%p) passed to NtGdiMaskBlt\n", hdcDest); 397 return FALSE; 398 } 399 400 if (DCDest->dctype == DC_TYPE_INFO) 401 { 402 if(DCSrc) DC_UnlockDc(DCSrc); 403 DC_UnlockDc(DCDest); 404 /* Yes, Windows really returns TRUE in this case */ 405 return TRUE; 406 } 407 408 if (UsesSource) 409 { 410 ASSERT(DCSrc); 411 if (DCSrc->dctype == DC_TYPE_INFO) 412 { 413 DC_UnlockDc(DCDest); 414 DC_UnlockDc(DCSrc); 415 /* Yes, Windows really returns TRUE in this case */ 416 return TRUE; 417 } 418 } 419 420 pdcattr = DCDest->pdcattr; 421 422 DestRect.left = nXDest; 423 DestRect.top = nYDest; 424 DestRect.right = nXDest + nWidth; 425 DestRect.bottom = nYDest + nHeight; 426 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); 427 428 DestRect.left += DCDest->ptlDCOrig.x; 429 DestRect.top += DCDest->ptlDCOrig.y; 430 DestRect.right += DCDest->ptlDCOrig.x; 431 DestRect.bottom += DCDest->ptlDCOrig.y; 432 433 if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 434 { 435 IntUpdateBoundsRect(DCDest, &DestRect); 436 } 437 438 SourcePoint.x = nXSrc; 439 SourcePoint.y = nYSrc; 440 441 if (UsesSource) 442 { 443 IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); 444 445 SourcePoint.x += DCSrc->ptlDCOrig.x; 446 SourcePoint.y += DCSrc->ptlDCOrig.y; 447 /* Calculate Source Rect */ 448 SourceRect.left = SourcePoint.x; 449 SourceRect.top = SourcePoint.y; 450 SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; 451 SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; 452 } 453 else 454 { 455 SourceRect.left = 0; 456 SourceRect.top = 0; 457 SourceRect.right = 0; 458 SourceRect.bottom = 0; 459 } 460 461 /* Prepare blit */ 462 DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); 463 464 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 465 DC_vUpdateFillBrush(DCDest); 466 467 /* Determine surfaces to be used in the bitblt */ 468 BitmapDest = DCDest->dclevel.pSurface; 469 if (!BitmapDest) 470 goto cleanup; 471 472 if (UsesSource) 473 { 474 BitmapSrc = DCSrc->dclevel.pSurface; 475 if (!BitmapSrc) 476 goto cleanup; 477 478 /* Create the XLATEOBJ. */ 479 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); 480 XlateObj = &exlo.xlo; 481 } 482 483 /* Perform the bitblt operation */ 484 Status = IntEngBitBlt(&BitmapDest->SurfObj, 485 BitmapSrc ? &BitmapSrc->SurfObj : NULL, 486 psurfMask ? &psurfMask->SurfObj : NULL, 487 (CLIPOBJ *)&DCDest->co, 488 XlateObj, 489 &DestRect, 490 &SourcePoint, 491 &MaskPoint, 492 &DCDest->eboFill.BrushObject, 493 &DCDest->dclevel.pbrFill->ptOrigin, 494 rop4); 495 496 if (UsesSource) 497 EXLATEOBJ_vCleanup(&exlo); 498 cleanup: 499 DC_vFinishBlit(DCDest, DCSrc); 500 if (UsesSource) 501 { 502 DC_UnlockDc(DCSrc); 503 } 504 DC_UnlockDc(DCDest); 505 if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask); 506 507 return Status; 508 } 509 510 BOOL 511 APIENTRY 512 NtGdiPlgBlt( 513 IN HDC hdcTrg, 514 IN LPPOINT pptlTrg, 515 IN HDC hdcSrc, 516 IN INT xSrc, 517 IN INT ySrc, 518 IN INT cxSrc, 519 IN INT cySrc, 520 IN HBITMAP hbmMask, 521 IN INT xMask, 522 IN INT yMask, 523 IN DWORD crBackColor) 524 { 525 FIXME("NtGdiPlgBlt: unimplemented.\n"); 526 return FALSE; 527 } 528 529 BOOL 530 NTAPI 531 GreStretchBltMask( 532 HDC hDCDest, 533 INT XOriginDest, 534 INT YOriginDest, 535 INT WidthDest, 536 INT HeightDest, 537 HDC hDCSrc, 538 INT XOriginSrc, 539 INT YOriginSrc, 540 INT WidthSrc, 541 INT HeightSrc, 542 DWORD dwRop4, 543 IN DWORD dwBackColor, 544 HDC hDCMask, 545 INT XOriginMask, 546 INT YOriginMask) 547 { 548 PDC DCDest; 549 PDC DCSrc = NULL; 550 PDC DCMask = NULL; 551 HDC ahDC[3]; 552 PGDIOBJ apObj[3]; 553 PDC_ATTR pdcattr; 554 SURFACE *BitmapDest, *BitmapSrc = NULL; 555 SURFACE *BitmapMask = NULL; 556 RECTL DestRect; 557 RECTL SourceRect; 558 POINTL MaskPoint; 559 BOOL Status = FALSE; 560 EXLATEOBJ exlo; 561 XLATEOBJ *XlateObj = NULL; 562 POINTL BrushOrigin; 563 BOOL UsesSource; 564 BOOL UsesMask; 565 ROP4 rop4; 566 567 rop4 = WIN32_ROP4_TO_ENG_ROP4(dwRop4); 568 569 UsesSource = ROP4_USES_SOURCE(rop4); 570 UsesMask = ROP4_USES_MASK(rop4); 571 572 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc) 573 { 574 EngSetLastError(ERROR_INVALID_PARAMETER); 575 return TRUE; 576 } 577 578 if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask)) 579 { 580 EngSetLastError(ERROR_INVALID_PARAMETER); 581 return FALSE; 582 } 583 584 ahDC[0] = hDCDest; 585 ahDC[1] = UsesSource ? hDCSrc : NULL; 586 ahDC[2] = UsesMask ? hDCMask : NULL; 587 if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) 588 { 589 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest, hDCSrc); 590 EngSetLastError(ERROR_INVALID_HANDLE); 591 return FALSE; 592 } 593 DCDest = apObj[0]; 594 DCSrc = apObj[1]; 595 DCMask = apObj[2]; 596 597 if (DCDest->dctype == DC_TYPE_INFO) 598 { 599 if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 600 if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject); 601 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 602 /* Yes, Windows really returns TRUE in this case */ 603 return TRUE; 604 } 605 606 if (UsesSource) 607 { 608 if (DCSrc->dctype == DC_TYPE_INFO) 609 { 610 GDIOBJ_vUnlockObject(&DCDest->BaseObject); 611 GDIOBJ_vUnlockObject(&DCSrc->BaseObject); 612 if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject); 613 /* Yes, Windows really returns TRUE in this case */ 614 return TRUE; 615 } 616 } 617 618 pdcattr = DCDest->pdcattr; 619 620 DestRect.left = XOriginDest; 621 DestRect.top = YOriginDest; 622 DestRect.right = XOriginDest+WidthDest; 623 DestRect.bottom = YOriginDest+HeightDest; 624 IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); 625 626 DestRect.left += DCDest->ptlDCOrig.x; 627 DestRect.top += DCDest->ptlDCOrig.y; 628 DestRect.right += DCDest->ptlDCOrig.x; 629 DestRect.bottom += DCDest->ptlDCOrig.y; 630 631 if (DCDest->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 632 { 633 IntUpdateBoundsRect(DCDest, &DestRect); 634 } 635 636 SourceRect.left = XOriginSrc; 637 SourceRect.top = YOriginSrc; 638 SourceRect.right = XOriginSrc+WidthSrc; 639 SourceRect.bottom = YOriginSrc+HeightSrc; 640 641 if (UsesSource) 642 { 643 IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2); 644 645 SourceRect.left += DCSrc->ptlDCOrig.x; 646 SourceRect.top += DCSrc->ptlDCOrig.y; 647 SourceRect.right += DCSrc->ptlDCOrig.x; 648 SourceRect.bottom += DCSrc->ptlDCOrig.y; 649 } 650 651 BrushOrigin.x = 0; 652 BrushOrigin.y = 0; 653 654 /* Only prepare Source and Dest, hdcMask represents a DIB */ 655 DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); 656 657 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 658 DC_vUpdateFillBrush(DCDest); 659 660 /* Determine surfaces to be used in the bitblt */ 661 BitmapDest = DCDest->dclevel.pSurface; 662 if (BitmapDest == NULL) 663 goto failed; 664 if (UsesSource) 665 { 666 BitmapSrc = DCSrc->dclevel.pSurface; 667 if (BitmapSrc == NULL) 668 goto failed; 669 670 /* Create the XLATEOBJ. */ 671 EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); 672 XlateObj = &exlo.xlo; 673 } 674 675 /* Offset the brush */ 676 BrushOrigin.x += DCDest->ptlDCOrig.x; 677 BrushOrigin.y += DCDest->ptlDCOrig.y; 678 679 /* Make mask surface for source surface */ 680 if (BitmapSrc && DCMask) 681 { 682 BitmapMask = DCMask->dclevel.pSurface; 683 if (BitmapMask && 684 (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc || 685 BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc)) 686 { 687 WARN("%dx%d mask is smaller than %dx%d bitmap\n", 688 BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy, 689 WidthSrc, HeightSrc); 690 EXLATEOBJ_vCleanup(&exlo); 691 goto failed; 692 } 693 /* Create mask offset point */ 694 MaskPoint.x = XOriginMask; 695 MaskPoint.y = YOriginMask; 696 IntLPtoDP(DCMask, &MaskPoint, 1); 697 MaskPoint.x += DCMask->ptlDCOrig.x; 698 MaskPoint.y += DCMask->ptlDCOrig.y; 699 } 700 701 /* Perform the bitblt operation */ 702 Status = IntEngStretchBlt(&BitmapDest->SurfObj, 703 BitmapSrc ? &BitmapSrc->SurfObj : NULL, 704 BitmapMask ? &BitmapMask->SurfObj : NULL, 705 (CLIPOBJ *)&DCDest->co, 706 XlateObj, 707 &DCDest->dclevel.ca, 708 &DestRect, 709 &SourceRect, 710 BitmapMask ? &MaskPoint : NULL, 711 &DCDest->eboFill.BrushObject, 712 &BrushOrigin, 713 rop4); 714 if (UsesSource) 715 { 716 EXLATEOBJ_vCleanup(&exlo); 717 } 718 719 failed: 720 DC_vFinishBlit(DCDest, DCSrc); 721 if (UsesSource) 722 { 723 DC_UnlockDc(DCSrc); 724 } 725 if (DCMask) 726 { 727 DC_UnlockDc(DCMask); 728 } 729 DC_UnlockDc(DCDest); 730 731 return Status; 732 } 733 734 735 BOOL APIENTRY 736 NtGdiStretchBlt( 737 HDC hDCDest, 738 INT XOriginDest, 739 INT YOriginDest, 740 INT WidthDest, 741 INT HeightDest, 742 HDC hDCSrc, 743 INT XOriginSrc, 744 INT YOriginSrc, 745 INT WidthSrc, 746 INT HeightSrc, 747 DWORD dwRop3, 748 IN DWORD dwBackColor) 749 { 750 dwRop3 = dwRop3 & ~(NOMIRRORBITMAP|CAPTUREBLT); 751 752 return GreStretchBltMask( 753 hDCDest, 754 XOriginDest, 755 YOriginDest, 756 WidthDest, 757 HeightDest, 758 hDCSrc, 759 XOriginSrc, 760 YOriginSrc, 761 WidthSrc, 762 HeightSrc, 763 MAKEROP4(dwRop3 & 0xFF0000, dwRop3), 764 dwBackColor, 765 NULL, 766 0, 767 0); 768 } 769 770 771 BOOL FASTCALL 772 IntPatBlt( 773 PDC pdc, 774 INT XLeft, 775 INT YLeft, 776 INT Width, 777 INT Height, 778 DWORD dwRop3, 779 PEBRUSHOBJ pebo) 780 { 781 RECTL DestRect; 782 SURFACE *psurf; 783 POINTL BrushOrigin; 784 BOOL ret; 785 PBRUSH pbrush; 786 787 ASSERT(pebo); 788 pbrush = pebo->pbrush; 789 ASSERT(pbrush); 790 791 if (pbrush->flAttrs & BR_IS_NULL) 792 { 793 return TRUE; 794 } 795 796 if (Width > 0) 797 { 798 DestRect.left = XLeft; 799 DestRect.right = XLeft + Width; 800 } 801 else 802 { 803 DestRect.left = XLeft + Width + 1; 804 DestRect.right = XLeft + 1; 805 } 806 807 if (Height > 0) 808 { 809 DestRect.top = YLeft; 810 DestRect.bottom = YLeft + Height; 811 } 812 else 813 { 814 DestRect.top = YLeft + Height + 1; 815 DestRect.bottom = YLeft + 1; 816 } 817 818 IntLPtoDP(pdc, (LPPOINT)&DestRect, 2); 819 820 DestRect.left += pdc->ptlDCOrig.x; 821 DestRect.top += pdc->ptlDCOrig.y; 822 DestRect.right += pdc->ptlDCOrig.x; 823 DestRect.bottom += pdc->ptlDCOrig.y; 824 825 if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 826 { 827 IntUpdateBoundsRect(pdc, &DestRect); 828 } 829 830 #ifdef _USE_DIBLIB_ 831 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft; 832 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft; 833 #else 834 BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x; 835 BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y; 836 #endif 837 838 DC_vPrepareDCsForBlit(pdc, &DestRect, NULL, NULL); 839 840 psurf = pdc->dclevel.pSurface; 841 842 ret = IntEngBitBlt(&psurf->SurfObj, 843 NULL, 844 NULL, 845 (CLIPOBJ *)&pdc->co, 846 NULL, 847 &DestRect, 848 NULL, 849 NULL, 850 &pebo->BrushObject, 851 &BrushOrigin, 852 WIN32_ROP3_TO_ENG_ROP4(dwRop3)); 853 854 DC_vFinishBlit(pdc, NULL); 855 856 return ret; 857 } 858 859 BOOL FASTCALL 860 IntGdiPolyPatBlt( 861 HDC hDC, 862 DWORD dwRop, 863 PPATRECT pRects, 864 INT cRects, 865 ULONG Reserved) 866 { 867 INT i; 868 PBRUSH pbrush; 869 PDC pdc; 870 EBRUSHOBJ eboFill; 871 872 pdc = DC_LockDc(hDC); 873 if (!pdc) 874 { 875 EngSetLastError(ERROR_INVALID_HANDLE); 876 return FALSE; 877 } 878 879 if (pdc->dctype == DC_TYPE_INFO) 880 { 881 DC_UnlockDc(pdc); 882 /* Yes, Windows really returns TRUE in this case */ 883 return TRUE; 884 } 885 886 for (i = 0; i < cRects; i++) 887 { 888 pbrush = BRUSH_ShareLockBrush(pRects->hBrush); 889 890 /* Check if we could lock the brush */ 891 if (pbrush != NULL) 892 { 893 /* Initialize a brush object */ 894 EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, pdc); 895 896 IntPatBlt( 897 pdc, 898 pRects->r.left, 899 pRects->r.top, 900 pRects->r.right, 901 pRects->r.bottom, 902 dwRop, 903 &eboFill); 904 905 /* Cleanup the brush object and unlock the brush */ 906 EBRUSHOBJ_vCleanup(&eboFill); 907 BRUSH_ShareUnlockBrush(pbrush); 908 } 909 pRects++; 910 } 911 912 DC_UnlockDc(pdc); 913 914 return TRUE; 915 } 916 917 BOOL 918 APIENTRY 919 NtGdiPatBlt( 920 _In_ HDC hdcDest, 921 _In_ INT x, 922 _In_ INT y, 923 _In_ INT cx, 924 _In_ INT cy, 925 _In_ DWORD dwRop) 926 { 927 BOOL bResult; 928 PDC pdc; 929 930 /* Convert the ROP3 to a ROP4 */ 931 dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop); 932 933 /* Check if the rop uses a source */ 934 if (WIN32_ROP4_USES_SOURCE(dwRop)) 935 { 936 /* This is not possible */ 937 return FALSE; 938 } 939 940 /* Lock the DC */ 941 pdc = DC_LockDc(hdcDest); 942 if (pdc == NULL) 943 { 944 EngSetLastError(ERROR_INVALID_HANDLE); 945 return FALSE; 946 } 947 948 /* Check if the DC has no surface (empty mem or info DC) */ 949 if (pdc->dclevel.pSurface == NULL) 950 { 951 /* Nothing to do, Windows returns TRUE! */ 952 DC_UnlockDc(pdc); 953 return TRUE; 954 } 955 956 /* Update the fill brush, if necessary */ 957 if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 958 DC_vUpdateFillBrush(pdc); 959 960 /* Call the internal function */ 961 bResult = IntPatBlt(pdc, x, y, cx, cy, dwRop, &pdc->eboFill); 962 963 /* Unlock the DC and return the result */ 964 DC_UnlockDc(pdc); 965 return bResult; 966 } 967 968 BOOL 969 APIENTRY 970 NtGdiPolyPatBlt( 971 HDC hDC, 972 DWORD dwRop, 973 IN PPOLYPATBLT pRects, 974 IN DWORD cRects, 975 IN DWORD Mode) 976 { 977 PPATRECT rb = NULL; 978 NTSTATUS Status = STATUS_SUCCESS; 979 BOOL Ret; 980 981 if (cRects > 0) 982 { 983 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, GDITAG_PLGBLT_DATA); 984 if (!rb) 985 { 986 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 987 return FALSE; 988 } 989 _SEH2_TRY 990 { 991 ProbeForRead(pRects, 992 cRects * sizeof(PATRECT), 993 1); 994 RtlCopyMemory(rb, 995 pRects, 996 cRects * sizeof(PATRECT)); 997 } 998 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 999 { 1000 Status = _SEH2_GetExceptionCode(); 1001 } 1002 _SEH2_END; 1003 1004 if (!NT_SUCCESS(Status)) 1005 { 1006 ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA); 1007 SetLastNtError(Status); 1008 return FALSE; 1009 } 1010 } 1011 1012 Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode); 1013 1014 if (cRects > 0) 1015 ExFreePoolWithTag(rb, GDITAG_PLGBLT_DATA); 1016 1017 return Ret; 1018 } 1019 1020 static 1021 BOOL 1022 FASTCALL 1023 REGION_LPTODP( 1024 _In_ PDC pdc, 1025 _Inout_ PREGION prgnDest, 1026 _In_ PREGION prgnSrc) 1027 { 1028 if (IntGdiCombineRgn(prgnDest, prgnSrc, NULL, RGN_COPY) == ERROR) 1029 return FALSE; 1030 1031 return REGION_bXformRgn(prgnDest, DC_pmxWorldToDevice(pdc)); 1032 } 1033 1034 BOOL 1035 APIENTRY 1036 IntGdiBitBltRgn( 1037 _In_ PDC pdc, 1038 _In_ PREGION prgn, 1039 _In_opt_ BRUSHOBJ *pbo, 1040 _In_opt_ POINTL *pptlBrush, 1041 _In_ ROP4 rop4) 1042 { 1043 PREGION prgnClip; 1044 XCLIPOBJ xcoClip; 1045 BOOL bResult; 1046 NT_ASSERT((pdc != NULL) && (prgn != NULL)); 1047 1048 /* Check if we have a surface */ 1049 if (pdc->dclevel.pSurface == NULL) 1050 { 1051 return TRUE; 1052 } 1053 1054 /* Create an empty clip region */ 1055 prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0); 1056 if (prgnClip == NULL) 1057 { 1058 return FALSE; 1059 } 1060 1061 /* Transform given region into device coordinates */ 1062 if (!REGION_LPTODP(pdc, prgnClip, prgn)) 1063 { 1064 REGION_Delete(prgnClip); 1065 return FALSE; 1066 } 1067 1068 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */ 1069 if (pdc->prgnRao) 1070 IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnRao, RGN_AND); 1071 else 1072 IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnVis, RGN_AND); 1073 1074 /* Now account for the DC-origin */ 1075 if (!REGION_bOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y)) 1076 { 1077 REGION_Delete(prgnClip); 1078 return FALSE; 1079 } 1080 1081 if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 1082 { 1083 RECTL rcrgn; 1084 REGION_GetRgnBox(prgnClip, &rcrgn); 1085 IntUpdateBoundsRect(pdc, &rcrgn); 1086 } 1087 1088 /* Prepare the DC */ 1089 DC_vPrepareDCsForBlit(pdc, &prgnClip->rdh.rcBound, NULL, NULL); 1090 1091 /* Initialize a clip object */ 1092 IntEngInitClipObj(&xcoClip); 1093 IntEngUpdateClipRegion(&xcoClip, 1094 prgnClip->rdh.nCount, 1095 prgnClip->Buffer, 1096 &prgnClip->rdh.rcBound); 1097 1098 /* Call the Eng or Drv function */ 1099 bResult = IntEngBitBlt(&pdc->dclevel.pSurface->SurfObj, 1100 NULL, 1101 NULL, 1102 (CLIPOBJ *)&xcoClip, 1103 NULL, 1104 &prgnClip->rdh.rcBound, 1105 NULL, 1106 NULL, 1107 pbo, 1108 pptlBrush, 1109 rop4); 1110 1111 /* Cleanup */ 1112 DC_vFinishBlit(pdc, NULL); 1113 REGION_Delete(prgnClip); 1114 IntEngFreeClipResources(&xcoClip); 1115 1116 /* Return the result */ 1117 return bResult; 1118 } 1119 1120 BOOL 1121 IntGdiFillRgn( 1122 _In_ PDC pdc, 1123 _In_ PREGION prgn, 1124 _In_opt_ PBRUSH pbrFill) 1125 { 1126 PREGION prgnClip; 1127 XCLIPOBJ xcoClip; 1128 EBRUSHOBJ eboFill; 1129 BRUSHOBJ *pbo; 1130 BOOL bRet; 1131 DWORD rop2Fg; 1132 MIX mix; 1133 NT_ASSERT((pdc != NULL) && (prgn != NULL)); 1134 1135 if (pdc->dclevel.pSurface == NULL) 1136 { 1137 return TRUE; 1138 } 1139 1140 prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0); 1141 if (prgnClip == NULL) 1142 { 1143 return FALSE; 1144 } 1145 1146 /* Transform region into device coordinates */ 1147 if (!REGION_LPTODP(pdc, prgnClip, prgn)) 1148 { 1149 REGION_Delete(prgnClip); 1150 return FALSE; 1151 } 1152 1153 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */ 1154 if (pdc->prgnRao) 1155 IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnRao, RGN_AND); 1156 else 1157 IntGdiCombineRgn(prgnClip, prgnClip, pdc->prgnVis, RGN_AND); 1158 1159 /* Now account for the DC-origin */ 1160 if (!REGION_bOffsetRgn(prgnClip, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y)) 1161 { 1162 REGION_Delete(prgnClip); 1163 return FALSE; 1164 } 1165 1166 if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 1167 { 1168 RECTL rcrgn; 1169 REGION_GetRgnBox(prgnClip, &rcrgn); 1170 IntUpdateBoundsRect(pdc, &rcrgn); 1171 } 1172 1173 IntEngInitClipObj(&xcoClip); 1174 IntEngUpdateClipRegion(&xcoClip, 1175 prgnClip->rdh.nCount, 1176 prgnClip->Buffer, 1177 &prgnClip->rdh.rcBound ); 1178 1179 /* Get the FG rop and create a MIX based on the BK mode */ 1180 rop2Fg = FIXUP_ROP2(pdc->pdcattr->jROP2); 1181 mix = rop2Fg | (pdc->pdcattr->jBkMode == OPAQUE ? rop2Fg : R2_NOP) << 8; 1182 1183 /* Prepare DC for blit */ 1184 DC_vPrepareDCsForBlit(pdc, &prgnClip->rdh.rcBound, NULL, NULL); 1185 1186 /* Check if we have a fill brush */ 1187 if (pbrFill != NULL) 1188 { 1189 /* Initialize the brush object */ 1190 /// \todo Check parameters 1191 EBRUSHOBJ_vInit(&eboFill, pbrFill, pdc->dclevel.pSurface, 0x00FFFFFF, 0, NULL); 1192 pbo = &eboFill.BrushObject; 1193 } 1194 else 1195 { 1196 /* Update the fill brush if needed */ 1197 if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) 1198 DC_vUpdateFillBrush(pdc); 1199 1200 /* Use the DC brush object */ 1201 pbo = &pdc->eboFill.BrushObject; 1202 } 1203 1204 /* Call the internal function */ 1205 bRet = IntEngPaint(&pdc->dclevel.pSurface->SurfObj, 1206 (CLIPOBJ *)&xcoClip, 1207 pbo, 1208 &pdc->pdcattr->ptlBrushOrigin, 1209 mix); 1210 1211 DC_vFinishBlit(pdc, NULL); 1212 REGION_Delete(prgnClip); 1213 IntEngFreeClipResources(&xcoClip); 1214 1215 // Fill the region 1216 return bRet; 1217 } 1218 1219 BOOL 1220 FASTCALL 1221 IntGdiPaintRgn( 1222 _In_ PDC pdc, 1223 _In_ PREGION prgn) 1224 { 1225 return IntGdiFillRgn(pdc, prgn, NULL); 1226 } 1227 1228 BOOL 1229 APIENTRY 1230 NtGdiFillRgn( 1231 _In_ HDC hdc, 1232 _In_ HRGN hrgn, 1233 _In_ HBRUSH hbrush) 1234 { 1235 PDC pdc; 1236 PREGION prgn; 1237 PBRUSH pbrFill; 1238 BOOL bResult; 1239 1240 /* Lock the DC */ 1241 pdc = DC_LockDc(hdc); 1242 if (pdc == NULL) 1243 { 1244 ERR("Failed to lock hdc %p\n", hdc); 1245 return FALSE; 1246 } 1247 1248 /* Check if the DC has no surface (empty mem or info DC) */ 1249 if (pdc->dclevel.pSurface == NULL) 1250 { 1251 DC_UnlockDc(pdc); 1252 return TRUE; 1253 } 1254 1255 /* Lock the region */ 1256 prgn = REGION_LockRgn(hrgn); 1257 if (prgn == NULL) 1258 { 1259 ERR("Failed to lock hrgn %p\n", hrgn); 1260 DC_UnlockDc(pdc); 1261 return FALSE; 1262 } 1263 1264 /* Lock the brush */ 1265 pbrFill = BRUSH_ShareLockBrush(hbrush); 1266 if (pbrFill == NULL) 1267 { 1268 ERR("Failed to lock hbrush %p\n", hbrush); 1269 REGION_UnlockRgn(prgn); 1270 DC_UnlockDc(pdc); 1271 return FALSE; 1272 } 1273 1274 /* Call the internal function */ 1275 bResult = IntGdiFillRgn(pdc, prgn, pbrFill); 1276 1277 /* Cleanup locks */ 1278 BRUSH_ShareUnlockBrush(pbrFill); 1279 REGION_UnlockRgn(prgn); 1280 DC_UnlockDc(pdc); 1281 1282 return bResult; 1283 } 1284 1285 BOOL 1286 APIENTRY 1287 NtGdiFrameRgn( 1288 _In_ HDC hdc, 1289 _In_ HRGN hrgn, 1290 _In_ HBRUSH hbrush, 1291 _In_ INT xWidth, 1292 _In_ INT yHeight) 1293 { 1294 HRGN hrgnFrame; 1295 BOOL bResult; 1296 1297 hrgnFrame = GreCreateFrameRgn(hrgn, xWidth, yHeight); 1298 if (hrgnFrame == NULL) 1299 { 1300 return FALSE; 1301 } 1302 1303 bResult = NtGdiFillRgn(hdc, hrgnFrame, hbrush); 1304 1305 GreDeleteObject(hrgnFrame); 1306 return bResult; 1307 } 1308 1309 BOOL 1310 APIENTRY 1311 NtGdiInvertRgn( 1312 _In_ HDC hdc, 1313 _In_ HRGN hrgn) 1314 { 1315 BOOL bResult; 1316 PDC pdc; 1317 PREGION prgn; 1318 1319 /* Lock the DC */ 1320 pdc = DC_LockDc(hdc); 1321 if (pdc == NULL) 1322 { 1323 EngSetLastError(ERROR_INVALID_HANDLE); 1324 return FALSE; 1325 } 1326 1327 /* Check if the DC has no surface (empty mem or info DC) */ 1328 if (pdc->dclevel.pSurface == NULL) 1329 { 1330 /* Nothing to do, Windows returns TRUE! */ 1331 DC_UnlockDc(pdc); 1332 return TRUE; 1333 } 1334 1335 /* Lock the region */ 1336 prgn = REGION_LockRgn(hrgn); 1337 if (prgn == NULL) 1338 { 1339 DC_UnlockDc(pdc); 1340 return FALSE; 1341 } 1342 1343 /* Call the internal function */ 1344 bResult = IntGdiBitBltRgn(pdc, 1345 prgn, 1346 NULL, // pbo 1347 NULL, // pptlBrush, 1348 ROP4_DSTINVERT); 1349 1350 /* Unlock the region and DC and return the result */ 1351 REGION_UnlockRgn(prgn); 1352 DC_UnlockDc(pdc); 1353 return bResult; 1354 } 1355 1356 COLORREF 1357 APIENTRY 1358 NtGdiSetPixel( 1359 _In_ HDC hdc, 1360 _In_ INT x, 1361 _In_ INT y, 1362 _In_ COLORREF crColor) 1363 { 1364 PDC pdc; 1365 ULONG iOldColor, iSolidColor; 1366 BOOL bResult; 1367 PEBRUSHOBJ pebo; 1368 ULONG ulDirty; 1369 EXLATEOBJ exlo; 1370 1371 /* Lock the DC */ 1372 pdc = DC_LockDc(hdc); 1373 if (!pdc) 1374 { 1375 EngSetLastError(ERROR_INVALID_HANDLE); 1376 return -1; 1377 } 1378 1379 /* Check if the DC has no surface (empty mem or info DC) */ 1380 if (pdc->dclevel.pSurface == NULL) 1381 { 1382 /* Fail! */ 1383 DC_UnlockDc(pdc); 1384 return -1; 1385 } 1386 1387 if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) 1388 { 1389 RECTL rcDst; 1390 1391 RECTL_vSetRect(&rcDst, x, y, x+1, y+1); 1392 1393 IntLPtoDP(pdc, (LPPOINT)&rcDst, 2); 1394 1395 rcDst.left += pdc->ptlDCOrig.x; 1396 rcDst.top += pdc->ptlDCOrig.y; 1397 rcDst.right += pdc->ptlDCOrig.x; 1398 rcDst.bottom += pdc->ptlDCOrig.y; 1399 1400 IntUpdateBoundsRect(pdc, &rcDst); 1401 } 1402 1403 /* Translate the color to the target format */ 1404 iSolidColor = TranslateCOLORREF(pdc, crColor); 1405 1406 /* Use the DC's text brush, which is always a solid brush */ 1407 pebo = &pdc->eboText; 1408 1409 /* Save the old solid color and set the one for the pixel */ 1410 iOldColor = EBRUSHOBJ_iSetSolidColor(pebo, iSolidColor); 1411 1412 /* Save dirty flags and reset dirty text brush flag */ 1413 ulDirty = pdc->pdcattr->ulDirty_; 1414 pdc->pdcattr->ulDirty_ &= ~DIRTY_TEXT; 1415 1416 /* Call the internal function */ 1417 bResult = IntPatBlt(pdc, x, y, 1, 1, PATCOPY, pebo); 1418 1419 /* Restore old text brush color and dirty flags */ 1420 EBRUSHOBJ_iSetSolidColor(pebo, iOldColor); 1421 pdc->pdcattr->ulDirty_ = ulDirty; 1422 1423 /// FIXME: we shouldn't dereference pSurface while the PDEV is not locked! 1424 /* Initialize an XLATEOBJ from the target surface to RGB */ 1425 EXLATEOBJ_vInitialize(&exlo, 1426 pdc->dclevel.pSurface->ppal, 1427 &gpalRGB, 1428 0, 1429 pdc->pdcattr->crBackgroundClr, 1430 pdc->pdcattr->crForegroundClr); 1431 1432 /* Translate the color back to RGB */ 1433 crColor = XLATEOBJ_iXlate(&exlo.xlo, iSolidColor); 1434 1435 /* Cleanup and return the target format color */ 1436 EXLATEOBJ_vCleanup(&exlo); 1437 1438 /* Unlock the DC */ 1439 DC_UnlockDc(pdc); 1440 1441 /* Return the new RGB color or -1 on failure */ 1442 return bResult ? crColor : -1; 1443 } 1444 1445 COLORREF 1446 APIENTRY 1447 NtGdiGetPixel( 1448 _In_ HDC hdc, 1449 _In_ INT x, 1450 _In_ INT y) 1451 { 1452 PDC pdc; 1453 ULONG ulRGBColor = CLR_INVALID; 1454 POINTL ptlSrc; 1455 RECT rcDest; 1456 PSURFACE psurfSrc, psurfDest; 1457 1458 /* Lock the DC */ 1459 pdc = DC_LockDc(hdc); 1460 if (!pdc) 1461 { 1462 EngSetLastError(ERROR_INVALID_HANDLE); 1463 return CLR_INVALID; 1464 } 1465 1466 /* Check if the DC has no surface (empty mem or info DC) */ 1467 if (pdc->dclevel.pSurface == NULL) 1468 { 1469 /* Fail! */ 1470 goto leave; 1471 } 1472 1473 /* Get the logical coordinates */ 1474 ptlSrc.x = x; 1475 ptlSrc.y = y; 1476 1477 /* Translate coordinates to device coordinates */ 1478 IntLPtoDP(pdc, &ptlSrc, 1); 1479 ptlSrc.x += pdc->ptlDCOrig.x; 1480 ptlSrc.y += pdc->ptlDCOrig.y; 1481 1482 rcDest.left = x; 1483 rcDest.top = y; 1484 rcDest.right = x + 1; 1485 rcDest.bottom = y + 1; 1486 1487 /* Prepare DC for blit */ 1488 DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL); 1489 1490 /* Check if the pixel is outside the surface */ 1491 psurfSrc = pdc->dclevel.pSurface; 1492 if ((ptlSrc.x >= psurfSrc->SurfObj.sizlBitmap.cx) || 1493 (ptlSrc.y >= psurfSrc->SurfObj.sizlBitmap.cy) || 1494 (ptlSrc.x < 0) || 1495 (ptlSrc.y < 0)) 1496 { 1497 /* Fail! */ 1498 goto leave; 1499 } 1500 1501 /* Allocate a surface */ 1502 psurfDest = SURFACE_AllocSurface(STYPE_BITMAP, 1503 1, 1504 1, 1505 BMF_32BPP, 1506 0, 1507 0, 1508 0, 1509 &ulRGBColor); 1510 if (psurfDest) 1511 { 1512 RECTL rclDest = {0, 0, 1, 1}; 1513 EXLATEOBJ exlo; 1514 1515 /* Translate from the source palette to RGB color */ 1516 EXLATEOBJ_vInitialize(&exlo, 1517 psurfSrc->ppal, 1518 &gpalRGB, 1519 0, 1520 RGB(0xff,0xff,0xff), 1521 RGB(0,0,0)); 1522 1523 /* Call the copy bits function */ 1524 EngCopyBits(&psurfDest->SurfObj, 1525 &psurfSrc->SurfObj, 1526 NULL, 1527 &exlo.xlo, 1528 &rclDest, 1529 &ptlSrc); 1530 1531 /* Cleanup the XLATEOBJ */ 1532 EXLATEOBJ_vCleanup(&exlo); 1533 1534 /* Delete the surface */ 1535 GDIOBJ_vDeleteObject(&psurfDest->BaseObject); 1536 } 1537 1538 leave: 1539 1540 /* Unlock the DC */ 1541 DC_vFinishBlit(pdc, NULL); 1542 DC_UnlockDc(pdc); 1543 1544 /* Return the new RGB color or -1 on failure */ 1545 return ulRGBColor; 1546 } 1547 1548