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