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