merge the formfield patch from ooo-build
[ooovba.git] / vcl / win / source / gdi / salgdi2.cxx
blob059e7155a123c3ee982bc5dbd0e2b98e99fe1382
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salgdi2.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <stdlib.h>
36 #include <tools/svwin.h>
37 #include <tools/debug.hxx>
38 #include <wincomp.hxx>
39 #include <salbmp.h>
40 #include <saldata.hxx>
41 #ifndef _SV_SALIDS_HRC
42 #include <salids.hrc>
43 #endif
44 #include <salgdi.h>
45 #include <salframe.h>
47 bool WinSalGraphics::supportsOperation( OutDevSupportType eType ) const
49 static bool bAllowForTest(true);
50 bool bRet = false;
52 switch( eType )
54 case OutDevSupport_TransparentRect:
55 bRet = mbVirDev || mbWindow;
56 break;
57 case OutDevSupport_B2DDraw:
58 bRet = bAllowForTest;
59 default: break;
61 return bRet;
64 // =======================================================================
66 void WinSalGraphics::copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics )
68 HDC hSrcDC;
69 DWORD nRop;
71 if ( pSrcGraphics )
72 hSrcDC = static_cast<WinSalGraphics*>(pSrcGraphics)->mhDC;
73 else
74 hSrcDC = mhDC;
76 if ( mbXORMode )
77 nRop = SRCINVERT;
78 else
79 nRop = SRCCOPY;
81 if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) &&
82 (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) )
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 );
91 else
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 );
105 // -----------------------------------------------------------------------
107 void ImplCalcOutSideRgn( const RECT& rSrcRect,
108 int nLeft, int nTop, int nRight, int nBottom,
109 HRGN& rhInvalidateRgn )
111 HRGN hTempRgn;
113 // Bereiche ausserhalb des sichtbaren Bereiches berechnen
114 if ( rSrcRect.left < nLeft )
116 if ( !rhInvalidateRgn )
117 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
118 hTempRgn = CreateRectRgn( -31999, 0, nLeft, 31999 );
119 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
120 DeleteRegion( hTempRgn );
122 if ( rSrcRect.top < nTop )
124 if ( !rhInvalidateRgn )
125 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
126 hTempRgn = CreateRectRgn( 0, -31999, 31999, nTop );
127 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
128 DeleteRegion( hTempRgn );
130 if ( rSrcRect.right > nRight )
132 if ( !rhInvalidateRgn )
133 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
134 hTempRgn = CreateRectRgn( nRight, 0, 31999, 31999 );
135 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
136 DeleteRegion( hTempRgn );
138 if ( rSrcRect.bottom > nBottom )
140 if ( !rhInvalidateRgn )
141 rhInvalidateRgn = CreateRectRgnIndirect( &rSrcRect );
142 hTempRgn = CreateRectRgn( 0, nBottom, 31999, 31999 );
143 CombineRgn( rhInvalidateRgn, rhInvalidateRgn, hTempRgn, RGN_DIFF );
144 DeleteRegion( hTempRgn );
148 // -----------------------------------------------------------------------
150 void WinSalGraphics::copyArea( long nDestX, long nDestY,
151 long nSrcX, long nSrcY,
152 long nSrcWidth, long nSrcHeight,
153 USHORT nFlags )
155 bool bRestoreClipRgn = false;
156 HRGN hOldClipRgn = 0;
157 int nOldClipRgnType = ERROR;
158 HRGN hInvalidateRgn = 0;
160 // Muessen die ueberlappenden Bereiche auch invalidiert werden?
161 if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow )
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;
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 ) )
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;
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 );
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 )
205 RECT aTempRect3 = aSrcRect;
208 hWndTopWindow = ::GetParent( hWndTopWindow );
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 );
222 while ( GetWindowStyle( hWndTopWindow ) & WS_CHILD );
224 // If one or more Parents clip our window, than we must
225 // calculate the outside area
226 if ( !EqualRect( &aSrcRect, &aTempRect3 ) )
228 ImplCalcOutSideRgn( aSrcRect,
229 aTempRect3.left, aTempRect3.top,
230 aTempRect3.right, aTempRect3.bottom,
231 hInvalidateRgn );
234 // retrieve the top-most (z-order) child window
235 hWnd = GetWindow( GetDesktopWindow(), GW_CHILD );
236 while ( hWnd )
238 if ( hWnd == hWndTopWindow )
239 break;
240 if ( IsWindowVisible( hWnd ) && !IsIconic( hWnd ) )
242 GetWindowRect( hWnd, &aTempRect );
243 if ( IntersectRect( &aTempRect2, &aSrcRect, &aTempRect ) )
245 // hWnd covers part or all of aSrcRect
246 if ( !hInvalidateRgn )
247 hInvalidateRgn = CreateRectRgnIndirect( &aSrcRect );
249 // get full bounding box of hWnd
250 hTempRgn = CreateRectRgnIndirect( &aTempRect );
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) )
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 );
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 );
268 // retrieve the next window in the z-order, i.e. the window below hwnd
269 hWnd = GetWindow( hWnd, GW_HWNDNEXT );
271 if ( hTempRgn2 )
272 DeleteRegion( hTempRgn2 );
273 if ( hInvalidateRgn )
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 );
281 if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) )
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 );
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 );
294 bRestoreClipRgn = TRUE; // indicate changed clipregion and force invalidate
295 ExtSelectClipRgn( mhDC, hInvalidateRgn, RGN_DIFF );
301 BitBlt( mhDC,
302 (int)nDestX, (int)nDestY,
303 (int)nSrcWidth, (int)nSrcHeight,
304 mhDC,
305 (int)nSrcX, (int)nSrcY,
306 SRCCOPY );
308 if( bRestoreClipRgn )
310 // restore old clip region
311 if( nOldClipRgnType != ERROR )
312 SelectClipRgn( mhDC, hOldClipRgn);
313 DeleteRegion( hOldClipRgn );
315 // invalidate regions that were not copied
316 bool bInvalidate = true;
318 // Combine Invalidate Region with existing ClipRegion
319 HRGN hTempRgn = CreateRectRgn( 0, 0, 0, 0 );
320 if ( GetClipRgn( mhDC, hTempRgn ) == 1 )
322 int nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_AND );
323 if ( (nRgnType == ERROR) || (nRgnType == NULLREGION) )
324 bInvalidate = false;
326 DeleteRegion( hTempRgn );
328 if ( bInvalidate )
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 );
341 DeleteRegion( hInvalidateRgn );
346 // -----------------------------------------------------------------------
348 void ImplDrawBitmap( HDC hDC,
349 const SalTwoRect* pPosAry, const WinSalBitmap& rSalBitmap,
350 BOOL bPrinter, int nDrawMode )
352 if( hDC )
354 HGLOBAL hDrawDIB;
355 HBITMAP hDrawDDB = rSalBitmap.ImplGethDDB();
356 WinSalBitmap* pTmpSalBmp = NULL;
357 BOOL bPrintDDB = ( bPrinter && hDrawDDB );
359 if( bPrintDDB )
361 pTmpSalBmp = new WinSalBitmap;
362 pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() );
363 hDrawDIB = pTmpSalBmp->ImplGethDIB();
365 else
366 hDrawDIB = rSalBitmap.ImplGethDIB();
368 if( hDrawDIB )
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 );
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 );
383 GlobalUnlock( hDrawDIB );
384 SetStretchBltMode( hDC, nOldStretchMode );
386 else if( hDrawDDB && !bPrintDDB )
388 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_DRAW, hDrawDDB );
389 COLORREF nOldBkColor = RGB(0xFF,0xFF,0xFF);
390 COLORREF nOldTextColor = RGB(0,0,0);
391 BOOL bMono = ( rSalBitmap.GetBitCount() == 1 );
393 if( bMono )
395 nOldBkColor = SetBkColor( hDC, RGB( 0xFF, 0xFF, 0xFF ) );
396 nOldTextColor = ::SetTextColor( hDC, RGB( 0x00, 0x00, 0x00 ) );
399 if ( (pPosAry->mnSrcWidth == pPosAry->mnDestWidth) &&
400 (pPosAry->mnSrcHeight == pPosAry->mnDestHeight) )
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 );
409 else
411 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS );
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 );
421 SetStretchBltMode( hDC, nOldStretchMode );
424 if( bMono )
426 SetBkColor( hDC, nOldBkColor );
427 ::SetTextColor( hDC, nOldTextColor );
430 ImplReleaseCachedDC( CACHED_HDC_DRAW );
433 if( bPrintDDB )
434 delete pTmpSalBmp;
438 // -----------------------------------------------------------------------
440 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
441 const SalBitmap& rSalBitmap )
443 ImplDrawBitmap( mhDC, pPosAry, static_cast<const WinSalBitmap&>(rSalBitmap),
444 mbPrinter,
445 mbXORMode ? SRCINVERT : SRCCOPY );
448 // -----------------------------------------------------------------------
450 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
451 const SalBitmap& rSSalBitmap,
452 SalColor nTransparentColor )
454 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
456 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
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 );
467 if( rSalBitmap.ImplGethDDB() )
469 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, rSalBitmap.ImplGethDDB() );
470 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) );
472 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY );
474 SetBkColor( hSrcDC, aOldCol );
475 ImplReleaseCachedDC( CACHED_HDC_2 );
477 else
479 WinSalBitmap* pTmpSalBmp = new WinSalBitmap;
481 if( pTmpSalBmp->Create( rSalBitmap, this ) )
483 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, pTmpSalBmp->ImplGethDDB() );
484 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) );
486 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY );
488 SetBkColor( hSrcDC, aOldCol );
489 ImplReleaseCachedDC( CACHED_HDC_2 );
492 delete pTmpSalBmp;
495 ImplReleaseCachedDC( CACHED_HDC_1 );
497 // hMaskBitmap is destroyed by new SalBitmap 'pMask' ( bDIB==FALSE, bCopy == FALSE )
498 if( pMask->Create( hMaskBitmap, FALSE, FALSE ) )
499 drawBitmap( pPosAry, rSalBitmap, *pMask );
501 delete pMask;
504 // -----------------------------------------------------------------------
506 void WinSalGraphics::drawBitmap( const SalTwoRect* pPosAry,
507 const SalBitmap& rSSalBitmap,
508 const SalBitmap& rSTransparentBitmap )
510 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
512 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
513 const WinSalBitmap& rTransparentBitmap = static_cast<const WinSalBitmap&>(rSTransparentBitmap);
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;
524 if( ( nDstWidth > CACHED_HDC_DEFEXT ) || ( nDstHeight > CACHED_HDC_DEFEXT ) )
526 hMemBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight );
527 hMaskBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight );
530 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, hMemBitmap );
531 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_2, hMaskBitmap );
533 aPosAry.mnDestX = aPosAry.mnDestY = 0;
534 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hDC, nDstX, nDstY, SRCCOPY );
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 )
541 WinSalBitmap aTmp;
543 if( aTmp.Create( rTransparentBitmap, this ) )
544 ImplDrawBitmap( hMaskDC, &aPosAry, aTmp, FALSE, SRCCOPY );
546 else
547 ImplDrawBitmap( hMaskDC, &aPosAry, rTransparentBitmap, FALSE, SRCCOPY );
549 // now MemDC contains background, MaskDC the transparency mask
551 // #105055# Respect XOR mode
552 if( mbXORMode )
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
559 else
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
568 // copy to output DC
569 BitBlt( hDC, nDstX, nDstY, nDstWidth, nDstHeight, hMemDC, 0, 0, SRCCOPY );
571 ImplReleaseCachedDC( CACHED_HDC_1 );
572 ImplReleaseCachedDC( CACHED_HDC_2 );
574 // hMemBitmap != 0 ==> hMaskBitmap != 0
575 if( hMemBitmap )
577 DeleteObject( hMemBitmap );
578 DeleteObject( hMaskBitmap );
582 // -----------------------------------------------------------------------
584 bool WinSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
585 const SalBitmap& rSrcBitmap,
586 const SalBitmap& rAlphaBmp )
588 (void)rTR; (void)rSrcBitmap; (void)rAlphaBmp;
590 // TODO(P3): implement alpha bmp blits. Catch: Windows only
591 // handles 32bpp, premultiplied bitmaps
592 return false;
595 // -----------------------------------------------------------------------
597 bool WinSalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
598 long nHeight, sal_uInt8 nTransparency )
600 if( mbPen || !mbBrush || mbXORMode )
601 return false; // can only perform solid fills without XOR.
603 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, 0 );
604 SetPixel( hMemDC, (int)0, (int)0, mnBrushColor );
606 BLENDFUNCTION aFunc = {
607 AC_SRC_OVER,
609 255 - 255L*nTransparency/100,
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;
619 ImplReleaseCachedDC( CACHED_HDC_1 );
621 return bRet;
624 // -----------------------------------------------------------------------
626 void WinSalGraphics::drawMask( const SalTwoRect* pPosAry,
627 const SalBitmap& rSSalBitmap,
628 SalColor nMaskColor )
630 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
632 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
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 );
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 )
647 WinSalBitmap aTmp;
649 if( aTmp.Create( rSalBitmap, this ) )
650 ImplDrawBitmap( hDC, &aPosAry, aTmp, FALSE, 0x00B8074AUL );
652 else
653 ImplDrawBitmap( hDC, &aPosAry, rSalBitmap, FALSE, 0x00B8074AUL );
655 SelectBrush( hDC, hOldBrush );
656 DeleteBrush( hMaskBrush );
659 // -----------------------------------------------------------------------
661 SalBitmap* WinSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
663 DBG_ASSERT( !mbPrinter, "No ::GetBitmap() from printer possible!" );
665 WinSalBitmap* pSalBitmap = NULL;
667 nDX = labs( nDX );
668 nDY = labs( nDY );
670 HDC hDC = mhDC;
671 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
672 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
673 BOOL bRet;
674 DWORD err = 0;
676 bRet = BitBlt( hBmpDC, 0, 0, (int) nDX, (int) nDY, hDC, (int) nX, (int) nY, SRCCOPY ) ? TRUE : FALSE;
677 ImplReleaseCachedDC( CACHED_HDC_1 );
679 if( bRet )
681 pSalBitmap = new WinSalBitmap;
683 if( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
685 delete pSalBitmap;
686 pSalBitmap = NULL;
689 else
691 err = GetLastError();
692 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers)
693 DeleteBitmap( hBmpBitmap );
696 return pSalBitmap;
699 // -----------------------------------------------------------------------
701 SalColor WinSalGraphics::getPixel( long nX, long nY )
703 COLORREF aWinCol = ::GetPixel( mhDC, (int) nX, (int) nY );
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 ) );
713 // -----------------------------------------------------------------------
715 void WinSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags )
717 if ( nFlags & SAL_INVERT_TRACKFRAME )
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 );
724 WIN_Rectangle( mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) );
726 SetROP2( mhDC, nOldROP );
727 SelectPen( mhDC, hOldPen );
728 SelectBrush( mhDC, hOldBrush );
729 DeletePen( hDotPen );
731 else if ( nFlags & SAL_INVERT_50 )
733 SalData* pSalData = GetSalData();
734 if ( !pSalData->mh50Brush )
736 if ( !pSalData->mh50Bmp )
737 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 );
738 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp );
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 );
747 else
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 );
758 // -----------------------------------------------------------------------
760 void WinSalGraphics::invert( ULONG nPoints, const SalPoint* pPtAry, SalInvert nSalFlags )
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 );
769 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
770 hPen = CreatePen( PS_DOT, 0, 0 );
771 else
774 if ( nSalFlags & SAL_INVERT_50 )
776 SalData* pSalData = GetSalData();
777 if ( !pSalData->mh50Brush )
779 if ( !pSalData->mh50Bmp )
780 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 );
781 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp );
784 hBrush = pSalData->mh50Brush;
786 else
787 hBrush = GetStockBrush( BLACK_BRUSH );
789 hPen = GetStockPen( NULL_PEN );
790 nOldTextColor = ::SetTextColor( mhDC, 0 );
791 hOldBrush = SelectBrush( mhDC, hBrush );
793 hOldPen = SelectPen( mhDC, hPen );
795 POINT* pWinPtAry;
796 // Unter NT koennen wir das Array direkt weiterreichen
797 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
798 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
800 pWinPtAry = (POINT*)pPtAry;
801 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
802 // von Punkten
803 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
805 if ( !Polyline( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
806 Polyline( mhDC, pWinPtAry, MAX_64KSALPOINTS );
808 else
810 if ( !WIN_Polygon( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
811 WIN_Polygon( mhDC, pWinPtAry, MAX_64KSALPOINTS );
814 SetROP2( mhDC, nOldROP );
815 SelectPen( mhDC, hOldPen );
817 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
818 DeletePen( hPen );
819 else
821 ::SetTextColor( mhDC, nOldTextColor );
822 SelectBrush( mhDC, hOldBrush );