1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salgdi2.cxx,v $
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"
36 #include <tools/svwin.h>
37 #include <tools/debug.hxx>
38 #include <wincomp.hxx>
40 #include <saldata.hxx>
41 #ifndef _SV_SALIDS_HRC
47 bool WinSalGraphics::supportsOperation( OutDevSupportType eType
) const
49 static bool bAllowForTest(true);
54 case OutDevSupport_TransparentRect
:
55 bRet
= mbVirDev
|| mbWindow
;
57 case OutDevSupport_B2DDraw
:
64 // =======================================================================
66 void WinSalGraphics::copyBits( const SalTwoRect
* pPosAry
, SalGraphics
* pSrcGraphics
)
72 hSrcDC
= static_cast<WinSalGraphics
*>(pSrcGraphics
)->mhDC
;
81 if ( (pPosAry
->mnSrcWidth
== pPosAry
->mnDestWidth
) &&
82 (pPosAry
->mnSrcHeight
== pPosAry
->mnDestHeight
) )
85 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
86 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
88 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
93 int nOldStretchMode
= SetStretchBltMode( mhDC
, STRETCH_DELETESCANS
);
95 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
96 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
98 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
99 (int)pPosAry
->mnSrcWidth
, (int)pPosAry
->mnSrcHeight
,
101 SetStretchBltMode( mhDC
, nOldStretchMode
);
105 // -----------------------------------------------------------------------
107 void ImplCalcOutSideRgn( const RECT
& rSrcRect
,
108 int nLeft
, int nTop
, int nRight
, int nBottom
,
109 HRGN
& rhInvalidateRgn
)
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
,
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
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
186 ClientToScreen( mhWnd
, &aPt
);
187 aSrcRect
.left
+= aPt
.x
;
188 aSrcRect
.top
+= aPt
.y
;
189 aSrcRect
.right
+= aPt
.x
;
190 aSrcRect
.bottom
+= aPt
.y
;
193 // compute the parts that are off screen (ie invisible)
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
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
);
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
,
234 // retrieve the top-most (z-order) child window
235 hWnd
= GetWindow( GetDesktopWindow(), GW_CHILD
);
238 if ( hWnd
== hWndTopWindow
)
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)
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
);
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
);
302 (int)nDestX
, (int)nDestY
,
303 (int)nSrcWidth
, (int)nSrcHeight
,
305 (int)nSrcX
, (int)nSrcY
,
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
) )
326 DeleteRegion( hTempRgn
);
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
)
355 HBITMAP hDrawDDB
= rSalBitmap
.ImplGethDDB();
356 WinSalBitmap
* pTmpSalBmp
= NULL
;
357 BOOL bPrintDDB
= ( bPrinter
&& hDrawDDB
);
361 pTmpSalBmp
= new WinSalBitmap
;
362 pTmpSalBmp
->Create( rSalBitmap
, rSalBitmap
.GetBitCount() );
363 hDrawDIB
= pTmpSalBmp
->ImplGethDIB();
366 hDrawDIB
= rSalBitmap
.ImplGethDIB();
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
);
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 );
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
) )
403 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
404 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
406 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
411 const int nOldStretchMode
= SetStretchBltMode( hDC
, STRETCH_DELETESCANS
);
414 (int)pPosAry
->mnDestX
, (int)pPosAry
->mnDestY
,
415 (int)pPosAry
->mnDestWidth
, (int)pPosAry
->mnDestHeight
,
417 (int)pPosAry
->mnSrcX
, (int)pPosAry
->mnSrcY
,
418 (int)pPosAry
->mnSrcWidth
, (int)pPosAry
->mnSrcHeight
,
421 SetStretchBltMode( hDC
, nOldStretchMode
);
426 SetBkColor( hDC
, nOldBkColor
);
427 ::SetTextColor( hDC
, nOldTextColor
);
430 ImplReleaseCachedDC( CACHED_HDC_DRAW
);
438 // -----------------------------------------------------------------------
440 void WinSalGraphics::drawBitmap( const SalTwoRect
* pPosAry
,
441 const SalBitmap
& rSalBitmap
)
443 ImplDrawBitmap( mhDC
, pPosAry
, static_cast<const WinSalBitmap
&>(rSalBitmap
),
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
;
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
);
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
);
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
);
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
;
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 )
543 if( aTmp
.Create( rTransparentBitmap
, this ) )
544 ImplDrawBitmap( hMaskDC
, &aPosAry
, aTmp
, FALSE
, SRCCOPY
);
547 ImplDrawBitmap( hMaskDC
, &aPosAry
, rTransparentBitmap
, FALSE
, SRCCOPY
);
549 // now MemDC contains background, MaskDC the transparency mask
551 // #105055# Respect XOR mode
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
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
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
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
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
= {
609 255 - 255L*nTransparency
/100,
613 // hMemDC contains a 1x1 bitmap of the right color - stretch-blit
615 bool bRet
= AlphaBlend( mhDC
, nX
, nY
, nWidth
, nHeight
,
619 ImplReleaseCachedDC( CACHED_HDC_1
);
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
);
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 )
649 if( aTmp
.Create( rSalBitmap
, this ) )
650 ImplDrawBitmap( hDC
, &aPosAry
, aTmp
, FALSE
, 0x00B8074AUL
);
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
;
671 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hDC
, nDX
, nDY
);
672 HDC hBmpDC
= ImplGetCachedDC( CACHED_HDC_1
, hBmpBitmap
);
676 bRet
= BitBlt( hBmpDC
, 0, 0, (int) nDX
, (int) nDY
, hDC
, (int) nX
, (int) nY
, SRCCOPY
) ? TRUE
: FALSE
;
677 ImplReleaseCachedDC( CACHED_HDC_1
);
681 pSalBitmap
= new WinSalBitmap
;
683 if( !pSalBitmap
->Create( hBmpBitmap
, FALSE
, FALSE
) )
691 err
= GetLastError();
692 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers)
693 DeleteBitmap( hBmpBitmap
);
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 );
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
);
750 aRect
.left
= (int)nX
;
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
)
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 );
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
;
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
);
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
803 if ( nSalFlags
& SAL_INVERT_TRACKFRAME
)
805 if ( !Polyline( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
806 Polyline( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
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
)
821 ::SetTextColor( mhDC
, nOldTextColor
);
822 SelectBrush( mhDC
, hOldBrush
);