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* pPosAry, SalGraphics* pSrcGraphics ) 63 { 64 HDC hSrcDC; 65 DWORD nRop; 66 67 if ( pSrcGraphics ) 68 hSrcDC = static_cast<WinSalGraphics*>(pSrcGraphics)->mhDC; 69 else 70 hSrcDC = mhDC; 71 72 if ( mbXORMode ) 73 nRop = SRCINVERT; 74 else 75 nRop = SRCCOPY; 76 77 if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) && 78 (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) ) 79 { 80 BitBlt( mhDC, 81 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, 82 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, 83 hSrcDC, 84 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, 85 nRop ); 86 } 87 else 88 { 89 int nOldStretchMode = SetStretchBltMode( mhDC, STRETCH_DELETESCANS ); 90 StretchBlt( mhDC, 91 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, 92 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, 93 hSrcDC, 94 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, 95 (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight, 96 nRop ); 97 SetStretchBltMode( mhDC, 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( mhDC, hOldClipRgn ); 289 290 bRestoreClipRgn = TRUE; // indicate changed clipregion and force invalidate 291 ExtSelectClipRgn( mhDC, hInvalidateRgn, RGN_DIFF ); 292 } 293 } 294 } 295 } 296 297 BitBlt( mhDC, 298 (int)nDestX, (int)nDestY, 299 (int)nSrcWidth, (int)nSrcHeight, 300 mhDC, 301 (int)nSrcX, (int)nSrcY, 302 SRCCOPY ); 303 304 if( bRestoreClipRgn ) 305 { 306 // restore old clip region 307 if( nOldClipRgnType != ERROR ) 308 SelectClipRgn( mhDC, 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( mhDC, 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* pPosAry, 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)pPosAry->mnDestX, (int)pPosAry->mnDestY, 374 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, 375 (int)pPosAry->mnSrcX, (int)(pBIH->biHeight - pPosAry->mnSrcHeight - pPosAry->mnSrcY), 376 (int)pPosAry->mnSrcWidth, (int)pPosAry->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 ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) && 396 (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) ) 397 { 398 BitBlt( hDC, 399 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, 400 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, 401 hBmpDC, 402 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, 403 nDrawMode ); 404 } 405 else 406 { 407 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS ); 408 409 StretchBlt( hDC, 410 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY, 411 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight, 412 hBmpDC, 413 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY, 414 (int)pPosAry->mnSrcWidth, (int)pPosAry->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* pPosAry, 437 const SalBitmap& rSalBitmap ) 438 { 439 ImplDrawBitmap( mhDC, pPosAry, static_cast<const WinSalBitmap&>(rSalBitmap), 440 mbPrinter, 441 mbXORMode ? SRCINVERT : SRCCOPY ); 442 } 443 444 // ----------------------------------------------------------------------- 445 446 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry, 447 const SalBitmap& rSSalBitmap, 448 SalColor nTransparentColor ) 449 { 450 DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); 451 452 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 453 454 WinSalBitmap* pMask = new WinSalBitmap; 455 const Point aPoint; 456 const Size aSize( rSalBitmap.GetSize() ); 457 HBITMAP hMaskBitmap = CreateBitmap( (int) aSize.Width(), (int) aSize.Height(), 1, 1, NULL ); 458 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_1, hMaskBitmap ); 459 const BYTE cRed = SALCOLOR_RED( nTransparentColor ); 460 const BYTE cGreen = SALCOLOR_GREEN( nTransparentColor ); 461 const BYTE cBlue = SALCOLOR_BLUE( nTransparentColor ); 462 463 if( rSalBitmap.ImplGethDDB() ) 464 { 465 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, rSalBitmap.ImplGethDDB() ); 466 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) ); 467 468 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY ); 469 470 SetBkColor( hSrcDC, aOldCol ); 471 ImplReleaseCachedDC( CACHED_HDC_2 ); 472 } 473 else 474 { 475 WinSalBitmap* pTmpSalBmp = new WinSalBitmap; 476 477 if( pTmpSalBmp->Create( rSalBitmap, this ) ) 478 { 479 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, pTmpSalBmp->ImplGethDDB() ); 480 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) ); 481 482 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY ); 483 484 SetBkColor( hSrcDC, aOldCol ); 485 ImplReleaseCachedDC( CACHED_HDC_2 ); 486 } 487 488 delete pTmpSalBmp; 489 } 490 491 ImplReleaseCachedDC( CACHED_HDC_1 ); 492 493 // hMaskBitmap is destroyed by new SalBitmap 'pMask' ( bDIB==FALSE, bCopy == FALSE ) 494 if( pMask->Create( hMaskBitmap, FALSE, FALSE ) ) 495 drawBitmap( pPosAry, rSalBitmap, *pMask ); 496 497 delete pMask; 498 } 499 500 // ----------------------------------------------------------------------- 501 502 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry, 503 const SalBitmap& rSSalBitmap, 504 const SalBitmap& rSTransparentBitmap ) 505 { 506 DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); 507 508 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 509 const WinSalBitmap& rTransparentBitmap = static_cast<const WinSalBitmap&>(rSTransparentBitmap); 510 511 SalTwoRect aPosAry = *pPosAry; 512 int nDstX = (int)aPosAry.mnDestX; 513 int nDstY = (int)aPosAry.mnDestY; 514 int nDstWidth = (int)aPosAry.mnDestWidth; 515 int nDstHeight = (int)aPosAry.mnDestHeight; 516 HDC hDC = mhDC; 517 HBITMAP hMemBitmap = 0; 518 HBITMAP hMaskBitmap = 0; 519 520 if( ( nDstWidth > CACHED_HDC_DEFEXT ) || ( nDstHeight > CACHED_HDC_DEFEXT ) ) 521 { 522 hMemBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight ); 523 hMaskBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight ); 524 } 525 526 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, hMemBitmap ); 527 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_2, hMaskBitmap ); 528 529 aPosAry.mnDestX = aPosAry.mnDestY = 0; 530 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hDC, nDstX, nDstY, SRCCOPY ); 531 532 // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, 533 // die Farben der Maske richtig auf die Palette abzubilden, 534 // wenn wir die DIB direkt ausgeben => DDB-Ausgabe 535 if( ( GetBitCount() <= 8 ) && rTransparentBitmap.ImplGethDIB() && rTransparentBitmap.GetBitCount() == 1 ) 536 { 537 WinSalBitmap aTmp; 538 539 if( aTmp.Create( rTransparentBitmap, this ) ) 540 ImplDrawBitmap( hMaskDC, &aPosAry, aTmp, FALSE, SRCCOPY ); 541 } 542 else 543 ImplDrawBitmap( hMaskDC, &aPosAry, rTransparentBitmap, FALSE, SRCCOPY ); 544 545 // now MemDC contains background, MaskDC the transparency mask 546 547 // #105055# Respect XOR mode 548 if( mbXORMode ) 549 { 550 ImplDrawBitmap( hMaskDC, &aPosAry, rSalBitmap, FALSE, SRCERASE ); 551 // now MaskDC contains the bitmap area with black background 552 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCINVERT ); 553 // now MemDC contains background XORed bitmap area ontop 554 } 555 else 556 { 557 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCAND ); 558 // now MemDC contains background with masked-out bitmap area 559 ImplDrawBitmap( hMaskDC, &aPosAry, rSalBitmap, FALSE, SRCERASE ); 560 // now MaskDC contains the bitmap area with black background 561 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCPAINT ); 562 // now MemDC contains background and bitmap merged together 563 } 564 // copy to output DC 565 BitBlt( hDC, nDstX, nDstY, nDstWidth, nDstHeight, hMemDC, 0, 0, SRCCOPY ); 566 567 ImplReleaseCachedDC( CACHED_HDC_1 ); 568 ImplReleaseCachedDC( CACHED_HDC_2 ); 569 570 // hMemBitmap != 0 ==> hMaskBitmap != 0 571 if( hMemBitmap ) 572 { 573 DeleteObject( hMemBitmap ); 574 DeleteObject( hMaskBitmap ); 575 } 576 } 577 578 // ----------------------------------------------------------------------- 579 580 bool WinSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, 581 const SalBitmap& rSrcBitmap, 582 const SalBitmap& rAlphaBmp ) 583 { 584 (void)rTR; (void)rSrcBitmap; (void)rAlphaBmp; 585 586 // TODO(P3): implement alpha bmp blits. Catch: Windows only 587 // handles 32bpp, premultiplied bitmaps 588 return false; 589 } 590 591 // ----------------------------------------------------------------------- 592 593 bool WinSalGraphics::drawAlphaRect( long nX, long nY, long nWidth, 594 long nHeight, sal_uInt8 nTransparency ) 595 { 596 if( mbPen || !mbBrush || mbXORMode ) 597 return false; // can only perform solid fills without XOR. 598 599 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, 0 ); 600 SetPixel( hMemDC, (int)0, (int)0, mnBrushColor ); 601 602 BLENDFUNCTION aFunc = { 603 AC_SRC_OVER, 604 0, 605 255 - 255L*nTransparency/100, 606 0 607 }; 608 609 // hMemDC contains a 1x1 bitmap of the right color - stretch-blit 610 // that to dest hdc 611 bool bRet = AlphaBlend( mhDC, nX, nY, nWidth, nHeight, 612 hMemDC, 0,0,1,1, 613 aFunc ) == TRUE; 614 615 ImplReleaseCachedDC( CACHED_HDC_1 ); 616 617 return bRet; 618 } 619 620 // ----------------------------------------------------------------------- 621 622 void WinSalGraphics::drawMask( const SalTwoRect* pPosAry, 623 const SalBitmap& rSSalBitmap, 624 SalColor nMaskColor ) 625 { 626 DBG_ASSERT( !mbPrinter, "No transparency print possible!" ); 627 628 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap); 629 630 SalTwoRect aPosAry = *pPosAry; 631 const BYTE cRed = SALCOLOR_RED( nMaskColor ); 632 const BYTE cGreen = SALCOLOR_GREEN( nMaskColor ); 633 const BYTE cBlue = SALCOLOR_BLUE( nMaskColor ); 634 HDC hDC = mhDC; 635 HBRUSH hMaskBrush = CreateSolidBrush( RGB( cRed, cGreen, cBlue ) ); 636 HBRUSH hOldBrush = SelectBrush( hDC, hMaskBrush ); 637 638 // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem, 639 // die Farben der Maske richtig auf die Palette abzubilden, 640 // wenn wir die DIB direkt ausgeben => DDB-Ausgabe 641 if( ( GetBitCount() <= 8 ) && rSalBitmap.ImplGethDIB() && rSalBitmap.GetBitCount() == 1 ) 642 { 643 WinSalBitmap aTmp; 644 645 if( aTmp.Create( rSalBitmap, this ) ) 646 ImplDrawBitmap( hDC, &aPosAry, aTmp, FALSE, 0x00B8074AUL ); 647 } 648 else 649 ImplDrawBitmap( hDC, &aPosAry, rSalBitmap, FALSE, 0x00B8074AUL ); 650 651 SelectBrush( hDC, hOldBrush ); 652 DeleteBrush( hMaskBrush ); 653 } 654 655 // ----------------------------------------------------------------------- 656 657 SalBitmap* WinSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY ) 658 { 659 DBG_ASSERT( !mbPrinter, "No ::GetBitmap() from printer possible!" ); 660 661 WinSalBitmap* pSalBitmap = NULL; 662 663 nDX = labs( nDX ); 664 nDY = labs( nDY ); 665 666 HDC hDC = mhDC; 667 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY ); 668 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap ); 669 sal_Bool bRet; 670 DWORD err = 0; 671 672 bRet = BitBlt( hBmpDC, 0, 0, (int) nDX, (int) nDY, hDC, (int) nX, (int) nY, SRCCOPY ) ? TRUE : FALSE; 673 ImplReleaseCachedDC( CACHED_HDC_1 ); 674 675 if( bRet ) 676 { 677 pSalBitmap = new WinSalBitmap; 678 679 if( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) ) 680 { 681 delete pSalBitmap; 682 pSalBitmap = NULL; 683 } 684 } 685 else 686 { 687 err = GetLastError(); 688 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers) 689 DeleteBitmap( hBmpBitmap ); 690 } 691 692 return pSalBitmap; 693 } 694 695 // ----------------------------------------------------------------------- 696 697 SalColor WinSalGraphics::getPixel( long nX, long nY ) 698 { 699 COLORREF aWinCol = ::GetPixel( mhDC, (int) nX, (int) nY ); 700 701 if ( CLR_INVALID == aWinCol ) 702 return MAKE_SALCOLOR( 0, 0, 0 ); 703 else 704 return MAKE_SALCOLOR( GetRValue( aWinCol ), 705 GetGValue( aWinCol ), 706 GetBValue( aWinCol ) ); 707 } 708 709 // ----------------------------------------------------------------------- 710 711 void WinSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) 712 { 713 if ( nFlags & SAL_INVERT_TRACKFRAME ) 714 { 715 HPEN hDotPen = CreatePen( PS_DOT, 0, 0 ); 716 HPEN hOldPen = SelectPen( mhDC, hDotPen ); 717 HBRUSH hOldBrush = SelectBrush( mhDC, GetStockBrush( NULL_BRUSH ) ); 718 int nOldROP = SetROP2( mhDC, R2_NOT ); 719 720 WIN_Rectangle( mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); 721 722 SetROP2( mhDC, nOldROP ); 723 SelectPen( mhDC, hOldPen ); 724 SelectBrush( mhDC, hOldBrush ); 725 DeletePen( hDotPen ); 726 } 727 else if ( nFlags & SAL_INVERT_50 ) 728 { 729 SalData* pSalData = GetSalData(); 730 if ( !pSalData->mh50Brush ) 731 { 732 if ( !pSalData->mh50Bmp ) 733 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 ); 734 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp ); 735 } 736 737 COLORREF nOldTextColor = ::SetTextColor( mhDC, 0 ); 738 HBRUSH hOldBrush = SelectBrush( mhDC, pSalData->mh50Brush ); 739 PatBlt( mhDC, nX, nY, nWidth, nHeight, PATINVERT ); 740 ::SetTextColor( mhDC, nOldTextColor ); 741 SelectBrush( mhDC, hOldBrush ); 742 } 743 else 744 { 745 RECT aRect; 746 aRect.left = (int)nX; 747 aRect.top = (int)nY; 748 aRect.right = (int)nX+nWidth; 749 aRect.bottom = (int)nY+nHeight; 750 ::InvertRect( mhDC, &aRect ); 751 } 752 } 753 754 // ----------------------------------------------------------------------- 755 756 void WinSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nSalFlags ) 757 { 758 HPEN hPen; 759 HPEN hOldPen; 760 HBRUSH hBrush; 761 HBRUSH hOldBrush = 0; 762 COLORREF nOldTextColor RGB(0,0,0); 763 int nOldROP = SetROP2( mhDC, R2_NOT ); 764 765 if ( nSalFlags & SAL_INVERT_TRACKFRAME ) 766 hPen = CreatePen( PS_DOT, 0, 0 ); 767 else 768 { 769 770 if ( nSalFlags & SAL_INVERT_50 ) 771 { 772 SalData* pSalData = GetSalData(); 773 if ( !pSalData->mh50Brush ) 774 { 775 if ( !pSalData->mh50Bmp ) 776 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 ); 777 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp ); 778 } 779 780 hBrush = pSalData->mh50Brush; 781 } 782 else 783 hBrush = GetStockBrush( BLACK_BRUSH ); 784 785 hPen = GetStockPen( NULL_PEN ); 786 nOldTextColor = ::SetTextColor( mhDC, 0 ); 787 hOldBrush = SelectBrush( mhDC, hBrush ); 788 } 789 hOldPen = SelectPen( mhDC, hPen ); 790 791 POINT* pWinPtAry; 792 // Unter NT koennen wir das Array direkt weiterreichen 793 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 794 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" ); 795 796 pWinPtAry = (POINT*)pPtAry; 797 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl 798 // von Punkten 799 if ( nSalFlags & SAL_INVERT_TRACKFRAME ) 800 { 801 if ( !Polyline( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 802 Polyline( mhDC, pWinPtAry, MAX_64KSALPOINTS ); 803 } 804 else 805 { 806 if ( !WIN_Polygon( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 807 WIN_Polygon( mhDC, pWinPtAry, MAX_64KSALPOINTS ); 808 } 809 810 SetROP2( mhDC, nOldROP ); 811 SelectPen( mhDC, hOldPen ); 812 813 if ( nSalFlags & SAL_INVERT_TRACKFRAME ) 814 DeletePen( hPen ); 815 else 816 { 817 ::SetTextColor( mhDC, nOldTextColor ); 818 SelectBrush( mhDC, hOldBrush ); 819 } 820 } 821