bump product version to 4.1.6.2
[LibreOffice.git] / vcl / win / source / gdi / salgdi2.cxx
blob3455c9c5e506b717f3b79175aec884f80e4d676f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <string.h>
22 #include <stdlib.h>
24 #include <svsys.h>
25 #include <tools/debug.hxx>
27 #include <win/wincomp.hxx>
28 #include <win/salbmp.h>
29 #include <win/saldata.hxx>
30 #include <win/salids.hrc>
31 #include <win/salgdi.h>
32 #include <win/salframe.h>
34 #include "vcl/salbtype.hxx"
35 #include "vcl/bmpacc.hxx"
36 #include "outdata.hxx"
38 bool WinSalGraphics::supportsOperation( OutDevSupportType eType ) const
40 static bool bAllowForTest(true);
41 bool bRet = false;
43 switch( eType )
45 case OutDevSupport_TransparentRect:
46 bRet = mbVirDev || mbWindow;
47 break;
48 case OutDevSupport_B2DClip:
49 bRet = true;
50 break;
51 case OutDevSupport_B2DDraw:
52 bRet = bAllowForTest;
53 default: break;
55 return bRet;
58 // =======================================================================
60 void WinSalGraphics::copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics )
62 HDC hSrcDC;
63 DWORD nRop;
65 if ( pSrcGraphics )
66 hSrcDC = static_cast<WinSalGraphics*>(pSrcGraphics)->mhDC;
67 else
68 hSrcDC = mhDC;
70 if ( mbXORMode )
71 nRop = SRCINVERT;
72 else
73 nRop = SRCCOPY;
75 if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) &&
76 (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) )
78 BitBlt( mhDC,
79 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY,
80 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight,
81 hSrcDC,
82 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY,
83 nRop );
85 else
87 int nOldStretchMode = SetStretchBltMode( mhDC, STRETCH_DELETESCANS );
88 StretchBlt( mhDC,
89 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY,
90 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight,
91 hSrcDC,
92 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY,
93 (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight,
94 nRop );
95 SetStretchBltMode( mhDC, nOldStretchMode );
99 // -----------------------------------------------------------------------
101 void ImplCalcOutSideRgn( const RECT& rSrcRect,
102 int nLeft, int nTop, int nRight, int nBottom,
103 HRGN& rhInvalidateRgn )
105 HRGN hTempRgn;
107 // calculate area outside the visible region
108 if ( rSrcRect.left < nLeft )
110 if ( !rhInvalidateRgn )
111 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
112 hTempRgn = CreateRectRgn( -31999, 0, nLeft, 31999 );
113 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
114 DeleteRegion( hTempRgn );
116 if ( rSrcRect.top < nTop )
118 if ( !rhInvalidateRgn )
119 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
120 hTempRgn = CreateRectRgn( 0, -31999, 31999, nTop );
121 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
122 DeleteRegion( hTempRgn );
124 if ( rSrcRect.right > nRight )
126 if ( !rhInvalidateRgn )
127 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
128 hTempRgn = CreateRectRgn( nRight, 0, 31999, 31999 );
129 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
130 DeleteRegion( hTempRgn );
132 if ( rSrcRect.bottom > nBottom )
134 if ( !rhInvalidateRgn )
135 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
136 hTempRgn = CreateRectRgn( 0, nBottom, 31999, 31999 );
137 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
138 DeleteRegion( hTempRgn );
142 // -----------------------------------------------------------------------
144 void WinSalGraphics::copyArea( long nDestX, long nDestY,
145 long nSrcX, long nSrcY,
146 long nSrcWidth, long nSrcHeight,
147 sal_uInt16 nFlags )
149 bool bRestoreClipRgn = false;
150 HRGN hOldClipRgn = 0;
151 int nOldClipRgnType = ERROR;
152 HRGN hInvalidateRgn = 0;
154 // do we have to invalidate also the overlaping regions?
155 if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow )
157 // compute and invalidate those parts that were either off-screen or covered by other windows
158 // while performing the above BitBlt
159 // those regions then have to be invalidated as they contain useless/wrong data
160 RECT aSrcRect;
161 RECT aClipRect;
162 RECT aTempRect;
163 RECT aTempRect2;
164 HRGN hTempRgn;
165 HWND hWnd;
167 // restrict srcRect to this window (calc intersection)
168 aSrcRect.left = (int)nSrcX;
169 aSrcRect.top = (int)nSrcY;
170 aSrcRect.right = aSrcRect.left+(int)nSrcWidth;
171 aSrcRect.bottom = aSrcRect.top+(int)nSrcHeight;
172 GetClientRect( mhWnd, &aClipRect );
173 if ( IntersectRect( &aSrcRect, &aSrcRect, &aClipRect ) )
175 // transform srcRect to screen coordinates
176 POINT aPt;
177 aPt.x = 0;
178 aPt.y = 0;
179 ClientToScreen( mhWnd, &aPt );
180 aSrcRect.left += aPt.x;
181 aSrcRect.top += aPt.y;
182 aSrcRect.right += aPt.x;
183 aSrcRect.bottom += aPt.y;
184 hInvalidateRgn = 0;
186 // compute the parts that are off screen (ie invisible)
187 RECT theScreen;
188 ImplSalGetWorkArea( NULL, &theScreen, NULL ); // find the screen area taking multiple monitors into account
189 ImplCalcOutSideRgn( aSrcRect, theScreen.left, theScreen.top, theScreen.right, theScreen.bottom, hInvalidateRgn );
191 // calculate regions that are covered by other windows
192 HRGN hTempRgn2 = 0;
193 HWND hWndTopWindow = mhWnd;
194 // Find the TopLevel Window, because only Windows which are in
195 // in the foreground of our TopLevel window must be considered
196 if ( GetWindowStyle( hWndTopWindow ) & WS_CHILD )
198 RECT aTempRect3 = aSrcRect;
201 hWndTopWindow = ::GetParent( hWndTopWindow );
203 // Test, if the Parent clips our window
204 GetClientRect( hWndTopWindow, &aTempRect );
205 POINT aPt2;
206 aPt2.x = 0;
207 aPt2.y = 0;
208 ClientToScreen( hWndTopWindow, &aPt2 );
209 aTempRect.left += aPt2.x;
210 aTempRect.top += aPt2.y;
211 aTempRect.right += aPt2.x;
212 aTempRect.bottom += aPt2.y;
213 IntersectRect( &aTempRect3, &aTempRect3, &aTempRect );
215 while ( GetWindowStyle( hWndTopWindow ) & WS_CHILD );
217 // If one or more Parents clip our window, than we must
218 // calculate the outside area
219 if ( !EqualRect( &aSrcRect, &aTempRect3 ) )
221 ImplCalcOutSideRgn( aSrcRect,
222 aTempRect3.left, aTempRect3.top,
223 aTempRect3.right, aTempRect3.bottom,
224 hInvalidateRgn );
227 // retrieve the top-most (z-order) child window
228 hWnd = GetWindow( GetDesktopWindow(), GW_CHILD );
229 while ( hWnd )
231 if ( hWnd == hWndTopWindow )
232 break;
233 if ( IsWindowVisible( hWnd ) && !IsIconic( hWnd ) )
235 GetWindowRect( hWnd, &aTempRect );
236 if ( IntersectRect( &aTempRect2, &aSrcRect, &aTempRect ) )
238 // hWnd covers part or all of aSrcRect
239 if ( !hInvalidateRgn )
240 hInvalidateRgn = CreateRectRgnIndirect( &aSrcRect );
242 // get full bounding box of hWnd
243 hTempRgn = CreateRectRgnIndirect( &aTempRect );
245 // get region of hWnd (the window may be shaped)
246 if ( !hTempRgn2 )
247 hTempRgn2 = CreateRectRgn( 0, 0, 0, 0 );
248 int nRgnType = GetWindowRgn( hWnd, hTempRgn2 );
249 if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) )
251 // convert window region to screen coordinates
252 OffsetRgn( hTempRgn2, aTempRect.left, aTempRect.top );
253 // and intersect with the window's bounding box
254 CombineRgn( hTempRgn, hTempRgn, hTempRgn2, RGN_AND );
256 // finally compute that part of aSrcRect which is not covered by any parts of hWnd
257 CombineRgn( hInvalidateRgn, hInvalidateRgn, hTempRgn, RGN_DIFF );
258 DeleteRegion( hTempRgn );
261 // retrieve the next window in the z-order, i.e. the window below hwnd
262 hWnd = GetWindow( hWnd, GW_HWNDNEXT );
264 if ( hTempRgn2 )
265 DeleteRegion( hTempRgn2 );
266 if ( hInvalidateRgn )
268 // hInvalidateRgn contains the fully visible parts of the original srcRect
269 hTempRgn = CreateRectRgnIndirect( &aSrcRect );
270 // substract it from the original rect to get the occluded parts
271 int nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_DIFF );
272 DeleteRegion( hTempRgn );
274 if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) )
276 // move the occluded parts to the destination pos
277 int nOffX = (int)(nDestX-nSrcX);
278 int nOffY = (int)(nDestY-nSrcY);
279 OffsetRgn( hInvalidateRgn, nOffX-aPt.x, nOffY-aPt.y );
281 // by excluding hInvalidateRgn from the system's clip region
282 // we will prevent bitblt from copying useless data
283 // epsecially now shadows from overlapping windows will appear (#i36344)
284 hOldClipRgn = CreateRectRgn( 0, 0, 0, 0 );
285 nOldClipRgnType = GetClipRgn( mhDC, hOldClipRgn );
287 bRestoreClipRgn = TRUE; // indicate changed clipregion and force invalidate
288 ExtSelectClipRgn( mhDC, hInvalidateRgn, RGN_DIFF );
294 BitBlt( mhDC,
295 (int)nDestX, (int)nDestY,
296 (int)nSrcWidth, (int)nSrcHeight,
297 mhDC,
298 (int)nSrcX, (int)nSrcY,
299 SRCCOPY );
301 if( bRestoreClipRgn )
303 // restore old clip region
304 if( nOldClipRgnType != ERROR )
305 SelectClipRgn( mhDC, hOldClipRgn);
306 DeleteRegion( hOldClipRgn );
308 // invalidate regions that were not copied
309 bool bInvalidate = true;
311 // Combine Invalidate Region with existing ClipRegion
312 HRGN hTempRgn = CreateRectRgn( 0, 0, 0, 0 );
313 if ( GetClipRgn( mhDC, hTempRgn ) == 1 )
315 int nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_AND );
316 if ( (nRgnType == ERROR) || (nRgnType == NULLREGION) )
317 bInvalidate = false;
319 DeleteRegion( hTempRgn );
321 if ( bInvalidate )
323 InvalidateRgn( mhWnd, hInvalidateRgn, TRUE );
324 // here we only initiate an update if this is the MainThread,
325 // so that there is no deadlock when handling the Paint event,
326 // as the SolarMutex is already held by this Thread
327 SalData* pSalData = GetSalData();
328 DWORD nCurThreadId = GetCurrentThreadId();
329 if ( pSalData->mnAppThreadId == nCurThreadId )
330 UpdateWindow( mhWnd );
333 DeleteRegion( hInvalidateRgn );
338 // -----------------------------------------------------------------------
340 void ImplDrawBitmap( HDC hDC,
341 const SalTwoRect* pPosAry, const WinSalBitmap& rSalBitmap,
342 sal_Bool bPrinter, int nDrawMode )
344 if( hDC )
346 HGLOBAL hDrawDIB;
347 HBITMAP hDrawDDB = rSalBitmap.ImplGethDDB();
348 WinSalBitmap* pTmpSalBmp = NULL;
349 sal_Bool bPrintDDB = ( bPrinter && hDrawDDB );
351 if( bPrintDDB )
353 pTmpSalBmp = new WinSalBitmap;
354 pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() );
355 hDrawDIB = pTmpSalBmp->ImplGethDIB();
357 else
358 hDrawDIB = rSalBitmap.ImplGethDIB();
360 if( hDrawDIB )
362 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDrawDIB );
363 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI;
364 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI +
365 rSalBitmap.ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD );
366 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS );
368 StretchDIBits( hDC,
369 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY,
370 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight,
371 (int)pPosAry->mnSrcX, (int)(pBIH->biHeight - pPosAry->mnSrcHeight - pPosAry->mnSrcY),
372 (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight,
373 pBits, pBI, DIB_RGB_COLORS, nDrawMode );
375 GlobalUnlock( hDrawDIB );
376 SetStretchBltMode( hDC, nOldStretchMode );
378 else if( hDrawDDB && !bPrintDDB )
380 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_DRAW, hDrawDDB );
381 COLORREF nOldBkColor = RGB(0xFF,0xFF,0xFF);
382 COLORREF nOldTextColor = RGB(0,0,0);
383 sal_Bool bMono = ( rSalBitmap.GetBitCount() == 1 );
385 if( bMono )
387 COLORREF nBkColor = RGB( 0xFF, 0xFF, 0xFF );
388 COLORREF nTextColor = RGB( 0x00, 0x00, 0x00 );
389 //fdo#33455 handle 1 bit depth pngs with palette entries
390 //to set fore/back colors
391 if (const BitmapBuffer* pBitmapBuffer = const_cast<WinSalBitmap&>(rSalBitmap).AcquireBuffer(true))
393 const BitmapPalette& rPalette = pBitmapBuffer->maPalette;
394 if (rPalette.GetEntryCount() == 2)
396 SalColor nCol;
397 nCol = ImplColorToSal(rPalette[0]);
398 nTextColor = RGB( SALCOLOR_RED(nCol), SALCOLOR_GREEN(nCol), SALCOLOR_BLUE(nCol) );
399 nCol = ImplColorToSal(rPalette[1]);
400 nBkColor = RGB( SALCOLOR_RED(nCol), SALCOLOR_GREEN(nCol), SALCOLOR_BLUE(nCol) );
403 nOldBkColor = SetBkColor( hDC, nBkColor );
404 nOldTextColor = ::SetTextColor( hDC, nTextColor );
407 if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) &&
408 (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) )
410 BitBlt( hDC,
411 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY,
412 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight,
413 hBmpDC,
414 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY,
415 nDrawMode );
417 else
419 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS );
421 StretchBlt( hDC,
422 (int)pPosAry->mnDestX, (int)pPosAry->mnDestY,
423 (int)pPosAry->mnDestWidth, (int)pPosAry->mnDestHeight,
424 hBmpDC,
425 (int)pPosAry->mnSrcX, (int)pPosAry->mnSrcY,
426 (int)pPosAry->mnSrcWidth, (int)pPosAry->mnSrcHeight,
427 nDrawMode );
429 SetStretchBltMode( hDC, nOldStretchMode );
432 if( bMono )
434 SetBkColor( hDC, nOldBkColor );
435 ::SetTextColor( hDC, nOldTextColor );
438 ImplReleaseCachedDC( CACHED_HDC_DRAW );
441 if( bPrintDDB )
442 delete pTmpSalBmp;
446 // -----------------------------------------------------------------------
448 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
449 const SalBitmap& rSalBitmap )
451 ImplDrawBitmap( mhDC, pPosAry, static_cast<const WinSalBitmap&>(rSalBitmap),
452 mbPrinter,
453 mbXORMode ? SRCINVERT : SRCCOPY );
456 // -----------------------------------------------------------------------
458 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
459 const SalBitmap& rSSalBitmap,
460 SalColor nTransparentColor )
462 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
464 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
466 WinSalBitmap* pMask = new WinSalBitmap;
467 const Point aPoint;
468 const Size aSize( rSalBitmap.GetSize() );
469 HBITMAP hMaskBitmap = CreateBitmap( (int) aSize.Width(), (int) aSize.Height(), 1, 1, NULL );
470 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_1, hMaskBitmap );
471 const BYTE cRed = SALCOLOR_RED( nTransparentColor );
472 const BYTE cGreen = SALCOLOR_GREEN( nTransparentColor );
473 const BYTE cBlue = SALCOLOR_BLUE( nTransparentColor );
475 if( rSalBitmap.ImplGethDDB() )
477 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, rSalBitmap.ImplGethDDB() );
478 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) );
480 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY );
482 SetBkColor( hSrcDC, aOldCol );
483 ImplReleaseCachedDC( CACHED_HDC_2 );
485 else
487 WinSalBitmap* pTmpSalBmp = new WinSalBitmap;
489 if( pTmpSalBmp->Create( rSalBitmap, this ) )
491 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, pTmpSalBmp->ImplGethDDB() );
492 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) );
494 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY );
496 SetBkColor( hSrcDC, aOldCol );
497 ImplReleaseCachedDC( CACHED_HDC_2 );
500 delete pTmpSalBmp;
503 ImplReleaseCachedDC( CACHED_HDC_1 );
505 // hMaskBitmap is destroyed by new SalBitmap 'pMask' ( bDIB==FALSE, bCopy == FALSE )
506 if( pMask->Create( hMaskBitmap, FALSE, FALSE ) )
507 drawBitmap( pPosAry, rSalBitmap, *pMask );
509 delete pMask;
512 // -----------------------------------------------------------------------
514 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
515 const SalBitmap& rSSalBitmap,
516 const SalBitmap& rSTransparentBitmap )
518 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
520 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
521 const WinSalBitmap& rTransparentBitmap = static_cast<const WinSalBitmap&>(rSTransparentBitmap);
523 SalTwoRect aPosAry = *pPosAry;
524 int nDstX = (int)aPosAry.mnDestX;
525 int nDstY = (int)aPosAry.mnDestY;
526 int nDstWidth = (int)aPosAry.mnDestWidth;
527 int nDstHeight = (int)aPosAry.mnDestHeight;
528 HDC hDC = mhDC;
529 HBITMAP hMemBitmap = 0;
530 HBITMAP hMaskBitmap = 0;
532 if( ( nDstWidth > CACHED_HDC_DEFEXT ) || ( nDstHeight > CACHED_HDC_DEFEXT ) )
534 hMemBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight );
535 hMaskBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight );
538 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, hMemBitmap );
539 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_2, hMaskBitmap );
541 aPosAry.mnDestX = aPosAry.mnDestY = 0;
542 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hDC, nDstX, nDstY, SRCCOPY );
544 // WIN/WNT seems to have a minor problem mapping the correct color of the
545 // mask to the palette if we draw the DIB directly ==> draw DDB
546 if( ( GetBitCount() <= 8 ) && rTransparentBitmap.ImplGethDIB() && rTransparentBitmap.GetBitCount() == 1 )
548 WinSalBitmap aTmp;
550 if( aTmp.Create( rTransparentBitmap, this ) )
551 ImplDrawBitmap( hMaskDC, &aPosAry, aTmp, FALSE, SRCCOPY );
553 else
554 ImplDrawBitmap( hMaskDC, &aPosAry, rTransparentBitmap, FALSE, SRCCOPY );
556 // now MemDC contains background, MaskDC the transparency mask
558 // #105055# Respect XOR mode
559 if( mbXORMode )
561 ImplDrawBitmap( hMaskDC, &aPosAry, rSalBitmap, FALSE, SRCERASE );
562 // now MaskDC contains the bitmap area with black background
563 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCINVERT );
564 // now MemDC contains background XORed bitmap area ontop
566 else
568 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCAND );
569 // now MemDC contains background with masked-out bitmap area
570 ImplDrawBitmap( hMaskDC, &aPosAry, rSalBitmap, FALSE, SRCERASE );
571 // now MaskDC contains the bitmap area with black background
572 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCPAINT );
573 // now MemDC contains background and bitmap merged together
575 // copy to output DC
576 BitBlt( hDC, nDstX, nDstY, nDstWidth, nDstHeight, hMemDC, 0, 0, SRCCOPY );
578 ImplReleaseCachedDC( CACHED_HDC_1 );
579 ImplReleaseCachedDC( CACHED_HDC_2 );
581 // hMemBitmap != 0 ==> hMaskBitmap != 0
582 if( hMemBitmap )
584 DeleteObject( hMemBitmap );
585 DeleteObject( hMaskBitmap );
589 // -----------------------------------------------------------------------
591 bool WinSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
592 const SalBitmap& rSrcBitmap,
593 const SalBitmap& rAlphaBmp )
595 (void)rTR; (void)rSrcBitmap; (void)rAlphaBmp;
597 // TODO(P3): implement alpha bmp blits. Catch: Windows only
598 // handles 32bpp, premultiplied bitmaps
599 return false;
602 // -----------------------------------------------------------------------
604 bool WinSalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
605 long nHeight, sal_uInt8 nTransparency )
607 if( mbPen || !mbBrush || mbXORMode )
608 return false; // can only perform solid fills without XOR.
610 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, 0 );
611 SetPixel( hMemDC, (int)0, (int)0, mnBrushColor );
613 BLENDFUNCTION aFunc = {
614 AC_SRC_OVER,
616 sal::static_int_cast<sal_uInt8>(255 - 255L*nTransparency/100),
620 // hMemDC contains a 1x1 bitmap of the right color - stretch-blit
621 // that to dest hdc
622 bool bRet = AlphaBlend( mhDC, nX, nY, nWidth, nHeight,
623 hMemDC, 0,0,1,1,
624 aFunc ) == TRUE;
626 ImplReleaseCachedDC( CACHED_HDC_1 );
628 return bRet;
631 // -----------------------------------------------------------------------
633 void WinSalGraphics::drawMask( const SalTwoRect* pPosAry,
634 const SalBitmap& rSSalBitmap,
635 SalColor nMaskColor )
637 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
639 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
641 SalTwoRect aPosAry = *pPosAry;
642 const BYTE cRed = SALCOLOR_RED( nMaskColor );
643 const BYTE cGreen = SALCOLOR_GREEN( nMaskColor );
644 const BYTE cBlue = SALCOLOR_BLUE( nMaskColor );
645 HDC hDC = mhDC;
646 HBRUSH hMaskBrush = CreateSolidBrush( RGB( cRed, cGreen, cBlue ) );
647 HBRUSH hOldBrush = SelectBrush( hDC, hMaskBrush );
649 // WIN/WNT seems to have a minor problem mapping the correct color of the
650 // mask to the palette if we draw the DIB directly ==> draw DDB
651 if( ( GetBitCount() <= 8 ) && rSalBitmap.ImplGethDIB() && rSalBitmap.GetBitCount() == 1 )
653 WinSalBitmap aTmp;
655 if( aTmp.Create( rSalBitmap, this ) )
656 ImplDrawBitmap( hDC, &aPosAry, aTmp, FALSE, 0x00B8074AUL );
658 else
659 ImplDrawBitmap( hDC, &aPosAry, rSalBitmap, FALSE, 0x00B8074AUL );
661 SelectBrush( hDC, hOldBrush );
662 DeleteBrush( hMaskBrush );
665 // -----------------------------------------------------------------------
667 SalBitmap* WinSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
669 DBG_ASSERT( !mbPrinter, "No ::GetBitmap() from printer possible!" );
671 WinSalBitmap* pSalBitmap = NULL;
673 nDX = labs( nDX );
674 nDY = labs( nDY );
676 HDC hDC = mhDC;
677 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
678 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
679 sal_Bool bRet;
681 bRet = BitBlt( hBmpDC, 0, 0, (int) nDX, (int) nDY, hDC, (int) nX, (int) nY, SRCCOPY ) ? TRUE : FALSE;
682 ImplReleaseCachedDC( CACHED_HDC_1 );
684 if( bRet )
686 pSalBitmap = new WinSalBitmap;
688 if( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
690 delete pSalBitmap;
691 pSalBitmap = NULL;
694 else
696 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers)
697 DeleteBitmap( hBmpBitmap );
700 return pSalBitmap;
703 // -----------------------------------------------------------------------
705 SalColor WinSalGraphics::getPixel( long nX, long nY )
707 COLORREF aWinCol = ::GetPixel( mhDC, (int) nX, (int) nY );
709 if ( CLR_INVALID == aWinCol )
710 return MAKE_SALCOLOR( 0, 0, 0 );
711 else
712 return MAKE_SALCOLOR( GetRValue( aWinCol ),
713 GetGValue( aWinCol ),
714 GetBValue( aWinCol ) );
717 // -----------------------------------------------------------------------
719 void WinSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags )
721 if ( nFlags & SAL_INVERT_TRACKFRAME )
723 HPEN hDotPen = CreatePen( PS_DOT, 0, 0 );
724 HPEN hOldPen = SelectPen( mhDC, hDotPen );
725 HBRUSH hOldBrush = SelectBrush( mhDC, GetStockBrush( NULL_BRUSH ) );
726 int nOldROP = SetROP2( mhDC, R2_NOT );
728 WIN_Rectangle( mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) );
730 SetROP2( mhDC, nOldROP );
731 SelectPen( mhDC, hOldPen );
732 SelectBrush( mhDC, hOldBrush );
733 DeletePen( hDotPen );
735 else if ( nFlags & SAL_INVERT_50 )
737 SalData* pSalData = GetSalData();
738 if ( !pSalData->mh50Brush )
740 if ( !pSalData->mh50Bmp )
741 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 );
742 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp );
745 COLORREF nOldTextColor = ::SetTextColor( mhDC, 0 );
746 HBRUSH hOldBrush = SelectBrush( mhDC, pSalData->mh50Brush );
747 PatBlt( mhDC, nX, nY, nWidth, nHeight, PATINVERT );
748 ::SetTextColor( mhDC, nOldTextColor );
749 SelectBrush( mhDC, hOldBrush );
751 else
753 RECT aRect;
754 aRect.left = (int)nX;
755 aRect.top = (int)nY;
756 aRect.right = (int)nX+nWidth;
757 aRect.bottom = (int)nY+nHeight;
758 ::InvertRect( mhDC, &aRect );
762 // -----------------------------------------------------------------------
764 void WinSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nSalFlags )
766 HPEN hPen;
767 HPEN hOldPen;
768 HBRUSH hBrush;
769 HBRUSH hOldBrush = 0;
770 COLORREF nOldTextColor RGB(0,0,0);
771 int nOldROP = SetROP2( mhDC, R2_NOT );
773 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
774 hPen = CreatePen( PS_DOT, 0, 0 );
775 else
778 if ( nSalFlags & SAL_INVERT_50 )
780 SalData* pSalData = GetSalData();
781 if ( !pSalData->mh50Brush )
783 if ( !pSalData->mh50Bmp )
784 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 );
785 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp );
788 hBrush = pSalData->mh50Brush;
790 else
791 hBrush = GetStockBrush( BLACK_BRUSH );
793 hPen = GetStockPen( NULL_PEN );
794 nOldTextColor = ::SetTextColor( mhDC, 0 );
795 hOldBrush = SelectBrush( mhDC, hBrush );
797 hOldPen = SelectPen( mhDC, hPen );
799 POINT* pWinPtAry;
800 // for NT, we can handover the array directly
801 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
802 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
804 pWinPtAry = (POINT*)pPtAry;
805 // for Windows 95 and its maximum number of points
806 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
808 if ( !Polyline( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
809 Polyline( mhDC, pWinPtAry, MAX_64KSALPOINTS );
811 else
813 if ( !WIN_Polygon( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
814 WIN_Polygon( mhDC, pWinPtAry, MAX_64KSALPOINTS );
817 SetROP2( mhDC, nOldROP );
818 SelectPen( mhDC, hOldPen );
820 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
821 DeletePen( hPen );
822 else
824 ::SetTextColor( mhDC, nOldTextColor );
825 SelectBrush( mhDC, hOldBrush );
829 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */