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