1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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);
45 case OutDevSupport_TransparentRect
:
46 bRet
= mbVirDev
|| mbWindow
;
48 case OutDevSupport_B2DClip
:
51 case OutDevSupport_B2DDraw
:
58 // =======================================================================
60 void WinSalGraphics::copyBits( const SalTwoRect
* pPosAry
, SalGraphics
* pSrcGraphics
)
66 hSrcDC
= static_cast<WinSalGraphics
*>(pSrcGraphics
)->mhDC
;
75 if ( (pPosAry
->mnSrcWidth
== pPosAry
->mnDestWidth
) &&
76 (pPosAry
->mnSrcHeight
== pPosAry
->mnDestHeight
) )
79 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
80 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
82 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
87 int nOldStretchMode
= SetStretchBltMode( mhDC
, STRETCH_DELETESCANS
);
89 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
90 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
92 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
93 (int)pPosAry
->mnSrcWidth
, (int)pPosAry
->mnSrcHeight
,
95 SetStretchBltMode( mhDC
, nOldStretchMode
);
99 // -----------------------------------------------------------------------
101 void ImplCalcOutSideRgn( const RECT
& rSrcRect
,
102 int nLeft
, int nTop
, int nRight
, int nBottom
,
103 HRGN
& rhInvalidateRgn
)
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
,
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
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
179 ClientToScreen( mhWnd
, &aPt
);
180 aSrcRect
.left
+= aPt
.x
;
181 aSrcRect
.top
+= aPt
.y
;
182 aSrcRect
.right
+= aPt
.x
;
183 aSrcRect
.bottom
+= aPt
.y
;
186 // compute the parts that are off screen (ie invisible)
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
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
);
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
,
227 // retrieve the top-most (z-order) child window
228 hWnd
= GetWindow( GetDesktopWindow(), GW_CHILD
);
231 if ( hWnd
== hWndTopWindow
)
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)
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
);
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
);
295 (int)nDestX
, (int)nDestY
,
296 (int)nSrcWidth
, (int)nSrcHeight
,
298 (int)nSrcX
, (int)nSrcY
,
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
) )
319 DeleteRegion( hTempRgn
);
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
)
347 HBITMAP hDrawDDB
= rSalBitmap
.ImplGethDDB();
348 WinSalBitmap
* pTmpSalBmp
= NULL
;
349 sal_Bool bPrintDDB
= ( bPrinter
&& hDrawDDB
);
353 pTmpSalBmp
= new WinSalBitmap
;
354 pTmpSalBmp
->Create( rSalBitmap
, rSalBitmap
.GetBitCount() );
355 hDrawDIB
= pTmpSalBmp
->ImplGethDIB();
358 hDrawDIB
= rSalBitmap
.ImplGethDIB();
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
);
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 );
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)
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
) )
411 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
412 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
414 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
419 const int nOldStretchMode
= SetStretchBltMode( hDC
, STRETCH_DELETESCANS
);
422 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
423 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
425 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
426 (int)pPosAry
->mnSrcWidth
, (int)pPosAry
->mnSrcHeight
,
429 SetStretchBltMode( hDC
, nOldStretchMode
);
434 SetBkColor( hDC
, nOldBkColor
);
435 ::SetTextColor( hDC
, nOldTextColor
);
438 ImplReleaseCachedDC( CACHED_HDC_DRAW
);
446 // -----------------------------------------------------------------------
448 void WinSalGraphics::drawBitmap( const SalTwoRect
* pPosAry
,
449 const SalBitmap
& rSalBitmap
)
451 ImplDrawBitmap( mhDC
, pPosAry
, static_cast<const WinSalBitmap
&>(rSalBitmap
),
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
;
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
);
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
);
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
);
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
;
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 )
550 if( aTmp
.Create( rTransparentBitmap
, this ) )
551 ImplDrawBitmap( hMaskDC
, &aPosAry
, aTmp
, FALSE
, SRCCOPY
);
554 ImplDrawBitmap( hMaskDC
, &aPosAry
, rTransparentBitmap
, FALSE
, SRCCOPY
);
556 // now MemDC contains background, MaskDC the transparency mask
558 // #105055# Respect XOR mode
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
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
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
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
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
= {
616 sal::static_int_cast
<sal_uInt8
>(255 - 255L*nTransparency
/100),
620 // hMemDC contains a 1x1 bitmap of the right color - stretch-blit
622 bool bRet
= AlphaBlend( mhDC
, nX
, nY
, nWidth
, nHeight
,
626 ImplReleaseCachedDC( CACHED_HDC_1
);
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
);
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 )
655 if( aTmp
.Create( rSalBitmap
, this ) )
656 ImplDrawBitmap( hDC
, &aPosAry
, aTmp
, FALSE
, 0x00B8074AUL
);
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
;
677 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hDC
, nDX
, nDY
);
678 HDC hBmpDC
= ImplGetCachedDC( CACHED_HDC_1
, hBmpBitmap
);
681 bRet
= BitBlt( hBmpDC
, 0, 0, (int) nDX
, (int) nDY
, hDC
, (int) nX
, (int) nY
, SRCCOPY
) ? TRUE
: FALSE
;
682 ImplReleaseCachedDC( CACHED_HDC_1
);
686 pSalBitmap
= new WinSalBitmap
;
688 if( !pSalBitmap
->Create( hBmpBitmap
, FALSE
, FALSE
) )
696 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers)
697 DeleteBitmap( hBmpBitmap
);
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 );
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
);
754 aRect
.left
= (int)nX
;
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
)
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 );
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
;
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
);
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
);
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
)
824 ::SetTextColor( mhDC
, nOldTextColor
);
825 SelectBrush( mhDC
, hOldBrush
);
829 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */