1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <string.h> 28 #include <stdlib.h> 29 30 #include <tools/svwin.h> 31 #include <tools/debug.hxx> 32 33 #include <win/wincomp.hxx> 34 #include <win/salbmp.h> 35 #include <win/saldata.hxx> 36 #include <win/salids.hrc> 37 #include <win/salgdi.h> 38 #include <win/salframe.h> 39 40 bool WinSalGraphics::supportsOperation( OutDevSupportType eType ) const 41 { 42 static bool bAllowForTest(true); 43 bool bRet = false; 44 45 switch( eType ) 46 { 47 case OutDevSupport_TransparentRect: 48 bRet = mbVirDev || mbWindow; 49 break; 50 case OutDevSupport_B2DClip: 51 bRet = true; 52 break; 53 case OutDevSupport_B2DDraw: 54 bRet = bAllowForTest; 55 default: break; 56 } 57 return bRet; 58 } 59 60 // ======================================================================= 61 62 void WinSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) 63 { 64 HDC hSrcDC; 65 DWORD nRop; 66 67 if ( pSrcGraphics ) 68 hSrcDC = static_cast<WinSalGraphics*>(pSrcGraphics)->getHDC(); 69 else 70 hSrcDC = getHDC(); 71 72 if ( mbXORMode ) 73 nRop = SRCINVERT; 74 else 75 nRop = SRCCOPY; 76 77 if ( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) && 78 (rPosAry.mnSrcHeight == rPosAry.mnDestHeight) ) 79 { 80 BitBlt( getHDC(), 81 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY, 82 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight, 83 hSrcDC, 84 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, 85 nRop ); 86 } 87 else 88 { 89 int nOldStretchMode = SetStretchBltMode( getHDC(), STRETCH_DELETESCANS ); 90 StretchBlt( getHDC(), 91 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY, 92 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight, 93 hSrcDC, 94 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, 95 (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight, 96 nRop ); 97 SetStretchBltMode( getHDC(), nOldStretchMode ); 98 } 99 } 100 101 // ----------------------------------------------------------------------- 102 103 void ImplCalcOutSideRgn( const RECT& rSrcRect, 104 int nLeft, int nTop, int nRight, int nBottom, 105 HRGN& rhInvalidateRgn ) 106 { 107 HRGN hTempRgn; 108 109 // Bereiche ausserhalb des sichtbaren Bereiches berechnen 110 if ( rSrcRect.left < nLeft ) 111 { 112 if ( !rhInvalidateRgn ) 113 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); 114 hTempRgn = CreateRectRgn( -31999, 0, nLeft, 31999 ); 115 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); 116 DeleteRegion( hTempRgn ); 117 } 118 if ( rSrcRect.top < nTop ) 119 { 120 if ( !rhInvalidateRgn ) 121 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); 122 hTempRgn = CreateRectRgn( 0, -31999, 31999, nTop ); 123 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); 124 DeleteRegion( hTempRgn ); 125 } 126 if ( rSrcRect.right > nRight ) 127 { 128 if ( !rhInvalidateRgn ) 129 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); 130 hTempRgn = CreateRectRgn( nRight, 0, 31999, 31999 ); 131 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); 132 DeleteRegion( hTempRgn ); 133 } 134 if ( rSrcRect.bottom > nBottom ) 135 { 136 if ( !rhInvalidateRgn ) 137 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect ); 138 hTempRgn = CreateRectRgn( 0, nBottom, 31999, 31999 ); 139 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF ); 140 DeleteRegion( hTempRgn ); 141 } 142 } 143 144 // ----------------------------------------------------------------------- 145 146 void WinSalGraphics::copyArea( long nDestX, long nDestY, 147 long nSrcX, long nSrcY, 148 long nSrcWidth, long nSrcHeight, 149 sal_uInt16 nFlags ) 150 { 151 bool bRestoreClipRgn = false; 152 HRGN hOldClipRgn = 0; 153 int nOldClipRgnType = ERROR; 154 HRGN hInvalidateRgn = 0; 155 156 // Muessen die ueberlappenden Bereiche auch invalidiert werden? 157 if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow ) 158 { 159 // compute and invalidate those parts that were either off-screen or covered by other windows 160 // while performing the above BitBlt 161 // those regions then have to be invalidated as they contain useless/wrong data 162 RECT aSrcRect; 163 RECT aClipRect; 164 RECT aTempRect; 165 RECT aTempRect2; 166 HRGN hTempRgn; 167 HWND hWnd; 168 int nRgnType; 169 170 // restrict srcRect to this window (calc intersection) 171 aSrcRect.left = (int)nSrcX; 172 aSrcRect.top = (int)nSrcY; 173 aSrcRect.right = aSrcRect.left+(int)nSrcWidth; 174 aSrcRect.bottom = aSrcRect.top+(int)nSrcHeight; 175 GetClientRect( mhWnd, &aClipRect ); 176 if ( IntersectRect( &aSrcRect, &aSrcRect, &aClipRect ) ) 177 { 178 // transform srcRect to screen coordinates 179 POINT aPt; 180 aPt.x = 0; 181 aPt.y = 0; 182 ClientToScreen( mhWnd, &aPt ); 183 aSrcRect.left += aPt.x; 184 aSrcRect.top += aPt.y; 185 aSrcRect.right += aPt.x; 186 aSrcRect.bottom += aPt.y; 187 hInvalidateRgn = 0; 188 189 // compute the parts that are off screen (ie invisible) 190 RECT theScreen; 191 ImplSalGetWorkArea( NULL, &theScreen, NULL ); // find the screen area taking multiple monitors into account 192 ImplCalcOutSideRgn( aSrcRect, theScreen.left, theScreen.top, theScreen.right, theScreen.bottom, hInvalidateRgn ); 193 194 // Bereiche die von anderen Fenstern ueberlagert werden berechnen 195 HRGN hTempRgn2 = 0; 196 HWND hWndTopWindow = mhWnd; 197 // Find the TopLevel Window, because only Windows which are in 198 // in the foreground of our TopLevel window must be considered 199 if ( GetWindowStyle( hWndTopWindow ) & WS_CHILD ) 200 { 201 RECT aTempRect3 = aSrcRect; 202 do 203 { 204 hWndTopWindow = ::GetParent( hWndTopWindow ); 205 206 // Test, if the Parent clips our window 207 GetClientRect( hWndTopWindow, &aTempRect ); 208 POINT aPt2; 209 aPt2.x = 0; 210 aPt2.y = 0; 211 ClientToScreen( hWndTopWindow, &aPt2 ); 212 aTempRect.left += aPt2.x; 213 aTempRect.top += aPt2.y; 214 aTempRect.right += aPt2.x; 215 aTempRect.bottom += aPt2.y; 216 IntersectRect( &aTempRect3, &aTempRect3, &aTempRect ); 217 } 218 while ( GetWindowStyle( hWndTopWindow ) & WS_CHILD ); 219 220 // If one or more Parents clip our window, than we must 221 // calculate the outside area 222 if ( !EqualRect( &aSrcRect, &aTempRect3 ) ) 223 { 224 ImplCalcOutSideRgn( aSrcRect, 225 aTempRect3.left, aTempRect3.top, 226 aTempRect3.right, aTempRect3.bottom, 227 hInvalidateRgn ); 228 } 229 } 230 // retrieve the top-most (z-order) child window 231 hWnd = GetWindow( GetDesktopWindow(), GW_CHILD ); 232 while ( hWnd ) 233 { 234 if ( hWnd == hWndTopWindow ) 235 break; 236 if ( IsWindowVisible( hWnd ) && !IsIconic( hWnd ) ) 237 { 238 GetWindowRect( hWnd, &aTempRect ); 239 if ( IntersectRect( &aTempRect2, &aSrcRect, &aTempRect ) ) 240 { 241 // hWnd covers part or all of aSrcRect 242 if ( !hInvalidateRgn ) 243 hInvalidateRgn = CreateRectRgnIndirect( &aSrcRect ); 244 245 // get full bounding box of hWnd 246 hTempRgn = CreateRectRgnIndirect( &aTempRect ); 247 248 // get region of hWnd (the window may be shaped) 249 if ( !hTempRgn2 ) 250 hTempRgn2 = CreateRectRgn( 0, 0, 0, 0 ); 251 nRgnType = GetWindowRgn( hWnd, hTempRgn2 ); 252 if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) ) 253 { 254 // convert window region to screen coordinates 255 OffsetRgn( hTempRgn2, aTempRect.left, aTempRect.top ); 256 // and intersect with the window's bounding box 257 CombineRgn( hTempRgn, hTempRgn, hTempRgn2, RGN_AND ); 258 } 259 // finally compute that part of aSrcRect which is not covered by any parts of hWnd 260 CombineRgn( hInvalidateRgn, hInvalidateRgn, hTempRgn, RGN_DIFF ); 261 DeleteRegion( hTempRgn ); 262 } 263 } 264 // retrieve the next window in the z-order, i.e. the window below hwnd 265 hWnd = GetWindow( hWnd, GW_HWNDNEXT ); 266 } 267 if ( hTempRgn2 ) 268 DeleteRegion( hTempRgn2 ); 269 if ( hInvalidateRgn ) 270 { 271 // hInvalidateRgn contains the fully visible parts of the original srcRect 272 hTempRgn = CreateRectRgnIndirect( &aSrcRect ); 273 // substract it from the original rect to get the occluded parts 274 nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_DIFF ); 275 DeleteRegion( hTempRgn ); 276 277 if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) ) 278 { 279 // move the occluded parts to the destination pos 280 int nOffX = (int)(nDestX-nSrcX); 281 int nOffY = (int)(nDestY-nSrcY); 282 OffsetRgn( hInvalidateRgn, nOffX-aPt.x, nOffY-aPt.y ); 283 284 // by excluding hInvalidateRgn from the system's clip region 285 // we will prevent bitblt from copying useless data 286 // epsecially now shadows from overlapping windows will appear (#i36344) 287 hOldClipRgn = CreateRectRgn( 0, 0, 0, 0 ); 288 nOldClipRgnType = GetClipRgn( getHDC(), hOldClipRgn ); 289 290 bRestoreClipRgn = TRUE; // indicate changed clipregion and force invalidate 291 ExtSelectClipRgn( getHDC(), hInvalidateRgn, RGN_DIFF ); 292 } 293 } 294 } 295 } 296 297 BitBlt( getHDC(), 298 (int)nDestX, (int)nDestY, 299 (int)nSrcWidth, (int)nSrcHeight, 300 getHDC(), 301 (int)nSrcX, (int)nSrcY, 302 SRCCOPY ); 303 304 if( bRestoreClipRgn ) 305 { 306 // restore old clip region 307 if( nOldClipRgnType != ERROR ) 308 SelectClipRgn( getHDC(), hOldClipRgn); 309 DeleteRegion( hOldClipRgn ); 310 311 // invalidate regions that were not copied 312 bool bInvalidate = true; 313 314 // Combine Invalidate Region with existing ClipRegion 315 HRGN hTempRgn = CreateRectRgn( 0, 0, 0, 0 ); 316 if ( GetClipRgn( getHDC(), hTempRgn ) == 1 ) 317 { 318 int nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_AND ); 319 if ( (nRgnType == ERROR) || (nRgnType == NULLREGION) ) 320 bInvalidate = false; 321 } 322 DeleteRegion( hTempRgn ); 323 324 if ( bInvalidate ) 325 { 326 InvalidateRgn( mhWnd, hInvalidateRgn, TRUE ); 327 // Hier loesen wir nur ein Update aus, wenn es der 328 // MainThread ist, damit es beim Bearbeiten der 329 // Paint-Message keinen Deadlock gibt, da der 330 // SolarMutex durch diesen Thread schon gelockt ist 331 SalData* pSalData = GetSalData(); 332 DWORD nCurThreadId = GetCurrentThreadId(); 333 if ( pSalData->mnAppThreadId == nCurThreadId ) 334 UpdateWindow( mhWnd ); 335 } 336 337 DeleteRegion( hInvalidateRgn ); 338 } 339 340 } 341 342 // ----------------------------------------------------------------------- 343 344 void ImplDrawBitmap( HDC hDC, 345 const SalTwoRect& rPosAry, const WinSalBitmap& rSalBitmap, 346 sal_Bool bPrinter, int nDrawMode ) 347 { 348 if( hDC ) 349 { 350 HGLOBAL hDrawDIB; 351 HBITMAP hDrawDDB = rSalBitmap.ImplGethDDB(); 352 WinSalBitmap* pTmpSalBmp = NULL; 353 sal_Bool bPrintDDB = ( bPrinter && hDrawDDB ); 354 355 if( bPrintDDB ) 356 { 357 pTmpSalBmp = new WinSalBitmap; 358 pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() ); 359 hDrawDIB = pTmpSalBmp->ImplGethDIB(); 360 } 361 else 362 hDrawDIB = rSalBitmap.ImplGethDIB(); 363 364 if( hDrawDIB ) 365 { 366 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDrawDIB ); 367 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 368 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 369 rSalBitmap.ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD ); 370 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS ); 371 372 StretchDIBits( hDC, 373 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY, 374 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight, 375 (int)rPosAry.mnSrcX, (int)(pBIH->biHeight - rPosAry.mnSrcHeight - rPosAry.mnSrcY), 376 (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight, 377 pBits, pBI, DIB_RGB_COLORS, nDrawMode ); 378 379 GlobalUnlock( hDrawDIB ); 380 SetStretchBltMode( hDC, nOldStretchMode ); 381 } 382 else if( hDrawDDB && !bPrintDDB ) 383 { 384 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_DRAW, hDrawDDB ); 385 COLORREF nOldBkColor = RGB(0xFF,0xFF,0xFF); 386 COLORREF nOldTextColor = RGB(0,0,0); 387 sal_Bool bMono = ( rSalBitmap.GetBitCount() == 1 ); 388 389 if( bMono ) 390 { 391 nOldBkColor = SetBkColor( hDC, RGB( 0xFF, 0xFF, 0xFF ) ); 392 nOldTextColor = ::SetTextColor( hDC, RGB( 0x00, 0x00, 0x00 ) ); 393 } 394 395 if ( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) && 396 (rPosAry.mnSrcHeight == rPosAry.mnDestHeight) ) 397 { 398 BitBlt( hDC, 399 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY, 400 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight, 401 hBmpDC, 402 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, 403 nDrawMode ); 404 } 405 else 406 { 407 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS ); 408 409 StretchBlt( hDC, 410 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY, 411 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight, 412 hBmpDC, 413 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY, 414 (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight, 415 nDrawMode ); 416 417 SetStretchBltMode( hDC, nOldStretchMode ); 418 } 419 420 if( bMono ) 421 { 422 SetBkColor( hDC, nOldBkColor ); 423 ::SetTextColor( hDC, nOldTextColor ); 424 } 425 426 ImplReleaseCachedDC( CACHED_HDC_DRAW ); 427 } 428 429 if( bPrintDDB ) 430 delete pTmpSalBmp; 431 } 432 } 433 434 // ----------------------------------------------------------------------- 435 436 void WinSalGraphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap) 437 { 438 bool bTryDirectPaint(!mbPrinter && !mbXORMode); 439 440 if(bTryDirectPaint) 441 { 442 // only paint direct when no scaling and no MapMode, else the 443 // more expensive conversions may be done for short-time Bitmap/BitmapEx 444 // used for buffering only 445 if(rPosAry.mnSrcWidth == rPosAry.mnDestWidth && rPosAry.mnSrcHeight == rPosAry.mnDestHeight) 446 { 447 bTryDirectPaint = false; 448 } 449 } 450 451 // try to draw using GdiPlus directly 452 if(bTryDirectPaint && tryDrawBitmapGdiPlus(rPosAry, rSalBitmap)) 453 { 454 return; 455 } 456 457 // fall back old stuff 458 ImplDrawBitmap(getHDC(), rPosAry, static_cast<const WinSalBitmap&>(rSalBitmap), 459 mbPrinter, 460 mbXORMode ? SRCINVERT : SRCCOPY ); 461 } 462 463 // ----------------------------------------------------------------------- 464 465 void WinSalGraphics::drawBitmap( const SalTwoRect& rPosAry, 466 const SalBitmap& rSSalBitmap, 467 SalColor nTransparentColor ) 468 { 469 DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); 470 471 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 472 473 WinSalBitmap* pMask = new WinSalBitmap; 474 const Point aPoint; 475 const Size aSize( rSalBitmap.GetSize() ); 476 HBITMAP hMaskBitmap = CreateBitmap( (int) aSize.Width(), (int) aSize.Height(), 1, 1, NULL ); 477 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_1, hMaskBitmap ); 478 const BYTE cRed = SALCOLOR_RED( nTransparentColor ); 479 const BYTE cGreen = SALCOLOR_GREEN( nTransparentColor ); 480 const BYTE cBlue = SALCOLOR_BLUE( nTransparentColor ); 481 482 if( rSalBitmap.ImplGethDDB() ) 483 { 484 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, rSalBitmap.ImplGethDDB() ); 485 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) ); 486 487 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY ); 488 489 SetBkColor( hSrcDC, aOldCol ); 490 ImplReleaseCachedDC( CACHED_HDC_2 ); 491 } 492 else 493 { 494 WinSalBitmap* pTmpSalBmp = new WinSalBitmap; 495 496 if( pTmpSalBmp->Create( rSalBitmap, this ) ) 497 { 498 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, pTmpSalBmp->ImplGethDDB() ); 499 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) ); 500 501 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY ); 502 503 SetBkColor( hSrcDC, aOldCol ); 504 ImplReleaseCachedDC( CACHED_HDC_2 ); 505 } 506 507 delete pTmpSalBmp; 508 } 509 510 ImplReleaseCachedDC( CACHED_HDC_1 ); 511 512 // hMaskBitmap is destroyed by new SalBitmap 'pMask' ( bDIB==FALSE, bCopy == FALSE ) 513 if( pMask->Create( hMaskBitmap, FALSE, FALSE ) ) 514 drawBitmap( rPosAry, rSalBitmap, *pMask ); 515 516 delete pMask; 517 } 518 519 // ----------------------------------------------------------------------- 520 521 void WinSalGraphics::drawBitmap( const SalTwoRect& rPosAry, 522 const SalBitmap& rSSalBitmap, 523 const SalBitmap& rSTransparentBitmap ) 524 { 525 DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); 526 bool bTryDirectPaint(!mbPrinter && !mbXORMode); 527 528 if(bTryDirectPaint) 529 { 530 // only paint direct when no scaling and no MapMode, else the 531 // more expensive conversions may be done for short-time Bitmap/BitmapEx 532 // used for buffering only 533 if(rPosAry.mnSrcWidth == rPosAry.mnDestWidth && rPosAry.mnSrcHeight == rPosAry.mnDestHeight) 534 { 535 bTryDirectPaint = false; 536 } 537 } 538 539 // try to draw using GdiPlus directly 540 if(bTryDirectPaint && drawAlphaBitmap(rPosAry, rSSalBitmap, rSTransparentBitmap)) 541 { 542 return; 543 } 544 545 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 546 const WinSalBitmap& rTransparentBitmap = static_cast<const WinSalBitmap&>(rSTransparentBitmap); 547 548 SalTwoRect aPosAry = rPosAry; 549 int nDstX = (int)aPosAry.mnDestX; 550 int nDstY = (int)aPosAry.mnDestY; 551 int nDstWidth = (int)aPosAry.mnDestWidth; 552 int nDstHeight = (int)aPosAry.mnDestHeight; 553 HDC hDC = getHDC(); 554 HBITMAP hMemBitmap = 0; 555 HBITMAP hMaskBitmap = 0; 556 557 if( ( nDstWidth > CACHED_HDC_DEFEXT ) || ( nDstHeight > CACHED_HDC_DEFEXT ) ) 558 { 559 hMemBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight ); 560 hMaskBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight ); 561 } 562 563 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, hMemBitmap ); 564 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_2, hMaskBitmap ); 565 566 aPosAry.mnDestX = aPosAry.mnDestY = 0; 567 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hDC, nDstX, nDstY, SRCCOPY ); 568 569 // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, 570 // die Farben der Maske richtig auf die Palette abzubilden, 571 // wenn wir die DIB direkt ausgeben => DDB-Ausgabe 572 if( ( GetBitCount() <= 8 ) && rTransparentBitmap.ImplGethDIB() && rTransparentBitmap.GetBitCount() == 1 ) 573 { 574 WinSalBitmap aTmp; 575 576 if( aTmp.Create( rTransparentBitmap, this ) ) 577 ImplDrawBitmap( hMaskDC, aPosAry, aTmp, FALSE, SRCCOPY ); 578 } 579 else 580 ImplDrawBitmap( hMaskDC, aPosAry, rTransparentBitmap, FALSE, SRCCOPY ); 581 582 // now MemDC contains background, MaskDC the transparency mask 583 584 // #105055# Respect XOR mode 585 if( mbXORMode ) 586 { 587 ImplDrawBitmap( hMaskDC, aPosAry, rSalBitmap, FALSE, SRCERASE ); 588 // now MaskDC contains the bitmap area with black background 589 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCINVERT ); 590 // now MemDC contains background XORed bitmap area ontop 591 } 592 else 593 { 594 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCAND ); 595 // now MemDC contains background with masked-out bitmap area 596 ImplDrawBitmap( hMaskDC, aPosAry, rSalBitmap, FALSE, SRCERASE ); 597 // now MaskDC contains the bitmap area with black background 598 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCPAINT ); 599 // now MemDC contains background and bitmap merged together 600 } 601 // copy to output DC 602 BitBlt( hDC, nDstX, nDstY, nDstWidth, nDstHeight, hMemDC, 0, 0, SRCCOPY ); 603 604 ImplReleaseCachedDC( CACHED_HDC_1 ); 605 ImplReleaseCachedDC( CACHED_HDC_2 ); 606 607 // hMemBitmap != 0 ==> hMaskBitmap != 0 608 if( hMemBitmap ) 609 { 610 DeleteObject( hMemBitmap ); 611 DeleteObject( hMaskBitmap ); 612 } 613 } 614 615 // ----------------------------------------------------------------------- 616 617 bool WinSalGraphics::drawAlphaRect( long nX, long nY, long nWidth, 618 long nHeight, sal_uInt8 nTransparency ) 619 { 620 if( mbPen || !mbBrush || mbXORMode ) 621 return false; // can only perform solid fills without XOR. 622 623 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, 0 ); 624 SetPixel( hMemDC, (int)0, (int)0, mnBrushColor ); 625 626 BLENDFUNCTION aFunc = { 627 AC_SRC_OVER, 628 0, 629 255 - 255L*nTransparency/100, 630 0 631 }; 632 633 // hMemDC contains a 1x1 bitmap of the right color - stretch-blit 634 // that to dest hdc 635 bool bRet = AlphaBlend( getHDC(), nX, nY, nWidth, nHeight, 636 hMemDC, 0,0,1,1, 637 aFunc ) == TRUE; 638 639 ImplReleaseCachedDC( CACHED_HDC_1 ); 640 641 return bRet; 642 } 643 644 // ----------------------------------------------------------------------- 645 646 void WinSalGraphics::drawMask( const SalTwoRect& rPosAry, 647 const SalBitmap& rSSalBitmap, 648 SalColor nMaskColor ) 649 { 650 DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); 651 652 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 653 654 SalTwoRect aPosAry = rPosAry; 655 const BYTE cRed = SALCOLOR_RED( nMaskColor ); 656 const BYTE cGreen = SALCOLOR_GREEN( nMaskColor ); 657 const BYTE cBlue = SALCOLOR_BLUE( nMaskColor ); 658 HDC hDC = getHDC(); 659 HBRUSH hMaskBrush = CreateSolidBrush( RGB( cRed, cGreen, cBlue ) ); 660 HBRUSH hOldBrush = SelectBrush( hDC, hMaskBrush ); 661 662 // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, 663 // die Farben der Maske richtig auf die Palette abzubilden, 664 // wenn wir die DIB direkt ausgeben => DDB-Ausgabe 665 if( ( GetBitCount() <= 8 ) && rSalBitmap.ImplGethDIB() && rSalBitmap.GetBitCount() == 1 ) 666 { 667 WinSalBitmap aTmp; 668 669 if( aTmp.Create( rSalBitmap, this ) ) 670 ImplDrawBitmap( hDC, aPosAry, aTmp, FALSE, 0x00B8074AUL ); 671 } 672 else 673 ImplDrawBitmap( hDC, aPosAry, rSalBitmap, FALSE, 0x00B8074AUL ); 674 675 SelectBrush( hDC, hOldBrush ); 676 DeleteBrush( hMaskBrush ); 677 } 678 679 // ----------------------------------------------------------------------- 680 681 SalBitmap* WinSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY ) 682 { 683 DBG_ASSERT( !mbPrinter, "No ::GetBitmap() from printer possible!" ); 684 685 WinSalBitmap* pSalBitmap = NULL; 686 687 nDX = labs( nDX ); 688 nDY = labs( nDY ); 689 690 HDC hDC = getHDC(); 691 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY ); 692 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap ); 693 sal_Bool bRet; 694 DWORD err = 0; 695 696 bRet = BitBlt( hBmpDC, 0, 0, (int) nDX, (int) nDY, hDC, (int) nX, (int) nY, SRCCOPY ) ? TRUE : FALSE; 697 ImplReleaseCachedDC( CACHED_HDC_1 ); 698 699 if( bRet ) 700 { 701 pSalBitmap = new WinSalBitmap; 702 703 if( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) ) 704 { 705 delete pSalBitmap; 706 pSalBitmap = NULL; 707 } 708 } 709 else 710 { 711 err = GetLastError(); 712 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers) 713 DeleteBitmap( hBmpBitmap ); 714 } 715 716 return pSalBitmap; 717 } 718 719 // ----------------------------------------------------------------------- 720 721 SalColor WinSalGraphics::getPixel( long nX, long nY ) 722 { 723 COLORREF aWinCol = ::GetPixel( getHDC(), (int) nX, (int) nY ); 724 725 if ( CLR_INVALID == aWinCol ) 726 return MAKE_SALCOLOR( 0, 0, 0 ); 727 else 728 return MAKE_SALCOLOR( GetRValue( aWinCol ), 729 GetGValue( aWinCol ), 730 GetBValue( aWinCol ) ); 731 } 732 733 // ----------------------------------------------------------------------- 734 735 void WinSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) 736 { 737 if ( nFlags & SAL_INVERT_TRACKFRAME ) 738 { 739 HPEN hDotPen = CreatePen( PS_DOT, 0, 0 ); 740 HPEN hOldPen = SelectPen( getHDC(), hDotPen ); 741 HBRUSH hOldBrush = SelectBrush( getHDC(), GetStockBrush( NULL_BRUSH ) ); 742 int nOldROP = SetROP2( getHDC(), R2_NOT ); 743 744 WIN_Rectangle( getHDC(), (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); 745 746 SetROP2( getHDC(), nOldROP ); 747 SelectPen( getHDC(), hOldPen ); 748 SelectBrush( getHDC(), hOldBrush ); 749 DeletePen( hDotPen ); 750 } 751 else if ( nFlags & SAL_INVERT_50 ) 752 { 753 SalData* pSalData = GetSalData(); 754 if ( !pSalData->mh50Brush ) 755 { 756 if ( !pSalData->mh50Bmp ) 757 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 ); 758 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp ); 759 } 760 761 COLORREF nOldTextColor = ::SetTextColor( getHDC(), 0 ); 762 HBRUSH hOldBrush = SelectBrush( getHDC(), pSalData->mh50Brush ); 763 PatBlt( getHDC(), nX, nY, nWidth, nHeight, PATINVERT ); 764 ::SetTextColor( getHDC(), nOldTextColor ); 765 SelectBrush( getHDC(), hOldBrush ); 766 } 767 else 768 { 769 RECT aRect; 770 aRect.left = (int)nX; 771 aRect.top = (int)nY; 772 aRect.right = (int)nX+nWidth; 773 aRect.bottom = (int)nY+nHeight; 774 ::InvertRect( getHDC(), &aRect ); 775 } 776 } 777 778 // ----------------------------------------------------------------------- 779 780 void WinSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nSalFlags ) 781 { 782 HPEN hPen; 783 HPEN hOldPen; 784 HBRUSH hBrush; 785 HBRUSH hOldBrush = 0; 786 COLORREF nOldTextColor RGB(0,0,0); 787 int nOldROP = SetROP2( getHDC(), R2_NOT ); 788 789 if ( nSalFlags & SAL_INVERT_TRACKFRAME ) 790 hPen = CreatePen( PS_DOT, 0, 0 ); 791 else 792 { 793 794 if ( nSalFlags & SAL_INVERT_50 ) 795 { 796 SalData* pSalData = GetSalData(); 797 if ( !pSalData->mh50Brush ) 798 { 799 if ( !pSalData->mh50Bmp ) 800 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 ); 801 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp ); 802 } 803 804 hBrush = pSalData->mh50Brush; 805 } 806 else 807 hBrush = GetStockBrush( BLACK_BRUSH ); 808 809 hPen = GetStockPen( NULL_PEN ); 810 nOldTextColor = ::SetTextColor( getHDC(), 0 ); 811 hOldBrush = SelectBrush( getHDC(), hBrush ); 812 } 813 hOldPen = SelectPen( getHDC(), hPen ); 814 815 POINT* pWinPtAry; 816 // Unter NT koennen wir das Array direkt weiterreichen 817 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 818 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" ); 819 820 pWinPtAry = (POINT*)pPtAry; 821 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl 822 // von Punkten 823 if ( nSalFlags & SAL_INVERT_TRACKFRAME ) 824 { 825 if ( !Polyline( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 826 Polyline( getHDC(), pWinPtAry, MAX_64KSALPOINTS ); 827 } 828 else 829 { 830 if ( !WIN_Polygon( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 831 WIN_Polygon( getHDC(), pWinPtAry, MAX_64KSALPOINTS ); 832 } 833 834 SetROP2( getHDC(), nOldROP ); 835 SelectPen( getHDC(), hOldPen ); 836 837 if ( nSalFlags & SAL_INVERT_TRACKFRAME ) 838 DeletePen( hPen ); 839 else 840 { 841 ::SetTextColor( getHDC(), nOldTextColor ); 842 SelectBrush( getHDC(), hOldBrush ); 843 } 844 } 845