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