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