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
supportsOperation(OutDevSupportType eType) const40 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
copyBits(const SalTwoRect & rPosAry,SalGraphics * pSrcGraphics)62 void WinSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
63 {
64 HDC hSrcDC;
65 DWORD nRop;
66
67 if ( pSrcGraphics )
68 hSrcDC = static_cast<WinSalGraphics*>(pSrcGraphics)->getHDC();
69 else
70 hSrcDC = getHDC();
71
72 if ( mbXORMode )
73 nRop = SRCINVERT;
74 else
75 nRop = SRCCOPY;
76
77 if ( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
78 (rPosAry.mnSrcHeight == rPosAry.mnDestHeight) )
79 {
80 BitBlt( getHDC(),
81 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY,
82 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight,
83 hSrcDC,
84 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY,
85 nRop );
86 }
87 else
88 {
89 int nOldStretchMode = SetStretchBltMode( getHDC(), STRETCH_DELETESCANS );
90 StretchBlt( getHDC(),
91 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY,
92 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight,
93 hSrcDC,
94 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY,
95 (int)rPosAry.mnSrcWidth, (int)rPosAry.mnSrcHeight,
96 nRop );
97 SetStretchBltMode( getHDC(), nOldStretchMode );
98 }
99 }
100
101 // -----------------------------------------------------------------------
102
ImplCalcOutSideRgn(const RECT & rSrcRect,int nLeft,int nTop,int nRight,int nBottom,HRGN & rhInvalidateRgn)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
copyArea(long nDestX,long nDestY,long nSrcX,long nSrcY,long nSrcWidth,long nSrcHeight,sal_uInt16 nFlags)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( getHDC(), hOldClipRgn );
289
290 bRestoreClipRgn = TRUE; // indicate changed clipregion and force invalidate
291 ExtSelectClipRgn( getHDC(), hInvalidateRgn, RGN_DIFF );
292 }
293 }
294 }
295 }
296
297 BitBlt( getHDC(),
298 (int)nDestX, (int)nDestY,
299 (int)nSrcWidth, (int)nSrcHeight,
300 getHDC(),
301 (int)nSrcX, (int)nSrcY,
302 SRCCOPY );
303
304 if( bRestoreClipRgn )
305 {
306 // restore old clip region
307 if( nOldClipRgnType != ERROR )
308 SelectClipRgn( getHDC(), 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( getHDC(), 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
ImplDrawBitmap(HDC hDC,const SalTwoRect & rPosAry,const WinSalBitmap & rSalBitmap,sal_Bool bPrinter,int nDrawMode)344 void ImplDrawBitmap( HDC hDC,
345 const SalTwoRect& rPosAry, 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)rPosAry.mnDestX, (int)rPosAry.mnDestY,
374 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight,
375 (int)rPosAry.mnSrcX, (int)(pBIH->biHeight - rPosAry.mnSrcHeight - rPosAry.mnSrcY),
376 (int)rPosAry.mnSrcWidth, (int)rPosAry.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 ( (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
396 (rPosAry.mnSrcHeight == rPosAry.mnDestHeight) )
397 {
398 BitBlt( hDC,
399 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY,
400 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight,
401 hBmpDC,
402 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY,
403 nDrawMode );
404 }
405 else
406 {
407 const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS );
408
409 StretchBlt( hDC,
410 (int)rPosAry.mnDestX, (int)rPosAry.mnDestY,
411 (int)rPosAry.mnDestWidth, (int)rPosAry.mnDestHeight,
412 hBmpDC,
413 (int)rPosAry.mnSrcX, (int)rPosAry.mnSrcY,
414 (int)rPosAry.mnSrcWidth, (int)rPosAry.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
drawBitmap(const SalTwoRect & rPosAry,const SalBitmap & rSalBitmap)436 void WinSalGraphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap)
437 {
438 bool bTryDirectPaint(!mbPrinter && !mbXORMode);
439
440 if(bTryDirectPaint)
441 {
442 // only paint direct when no scaling and no MapMode, else the
443 // more expensive conversions may be done for short-time Bitmap/BitmapEx
444 // used for buffering only
445 if(rPosAry.mnSrcWidth == rPosAry.mnDestWidth && rPosAry.mnSrcHeight == rPosAry.mnDestHeight)
446 {
447 bTryDirectPaint = false;
448 }
449 }
450
451 // try to draw using GdiPlus directly
452 if(bTryDirectPaint && tryDrawBitmapGdiPlus(rPosAry, rSalBitmap))
453 {
454 return;
455 }
456
457 // fall back old stuff
458 ImplDrawBitmap(getHDC(), rPosAry, static_cast<const WinSalBitmap&>(rSalBitmap),
459 mbPrinter,
460 mbXORMode ? SRCINVERT : SRCCOPY );
461 }
462
463 // -----------------------------------------------------------------------
464
drawBitmap(const SalTwoRect & rPosAry,const SalBitmap & rSSalBitmap,SalColor nTransparentColor)465 void WinSalGraphics::drawBitmap( const SalTwoRect& rPosAry,
466 const SalBitmap& rSSalBitmap,
467 SalColor nTransparentColor )
468 {
469 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
470
471 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
472
473 WinSalBitmap* pMask = new WinSalBitmap;
474 const Point aPoint;
475 const Size aSize( rSalBitmap.GetSize() );
476 HBITMAP hMaskBitmap = CreateBitmap( (int) aSize.Width(), (int) aSize.Height(), 1, 1, NULL );
477 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_1, hMaskBitmap );
478 const BYTE cRed = SALCOLOR_RED( nTransparentColor );
479 const BYTE cGreen = SALCOLOR_GREEN( nTransparentColor );
480 const BYTE cBlue = SALCOLOR_BLUE( nTransparentColor );
481
482 if( rSalBitmap.ImplGethDDB() )
483 {
484 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, rSalBitmap.ImplGethDDB() );
485 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) );
486
487 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY );
488
489 SetBkColor( hSrcDC, aOldCol );
490 ImplReleaseCachedDC( CACHED_HDC_2 );
491 }
492 else
493 {
494 WinSalBitmap* pTmpSalBmp = new WinSalBitmap;
495
496 if( pTmpSalBmp->Create( rSalBitmap, this ) )
497 {
498 HDC hSrcDC = ImplGetCachedDC( CACHED_HDC_2, pTmpSalBmp->ImplGethDDB() );
499 COLORREF aOldCol = SetBkColor( hSrcDC, RGB( cRed, cGreen, cBlue ) );
500
501 BitBlt( hMaskDC, 0, 0, (int) aSize.Width(), (int) aSize.Height(), hSrcDC, 0, 0, SRCCOPY );
502
503 SetBkColor( hSrcDC, aOldCol );
504 ImplReleaseCachedDC( CACHED_HDC_2 );
505 }
506
507 delete pTmpSalBmp;
508 }
509
510 ImplReleaseCachedDC( CACHED_HDC_1 );
511
512 // hMaskBitmap is destroyed by new SalBitmap 'pMask' ( bDIB==FALSE, bCopy == FALSE )
513 if( pMask->Create( hMaskBitmap, FALSE, FALSE ) )
514 drawBitmap( rPosAry, rSalBitmap, *pMask );
515
516 delete pMask;
517 }
518
519 // -----------------------------------------------------------------------
520
drawBitmap(const SalTwoRect & rPosAry,const SalBitmap & rSSalBitmap,const SalBitmap & rSTransparentBitmap)521 void WinSalGraphics::drawBitmap( const SalTwoRect& rPosAry,
522 const SalBitmap& rSSalBitmap,
523 const SalBitmap& rSTransparentBitmap )
524 {
525 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
526 bool bTryDirectPaint(!mbPrinter && !mbXORMode);
527
528 if(bTryDirectPaint)
529 {
530 // only paint direct when no scaling and no MapMode, else the
531 // more expensive conversions may be done for short-time Bitmap/BitmapEx
532 // used for buffering only
533 if(rPosAry.mnSrcWidth == rPosAry.mnDestWidth && rPosAry.mnSrcHeight == rPosAry.mnDestHeight)
534 {
535 bTryDirectPaint = false;
536 }
537 }
538
539 // try to draw using GdiPlus directly
540 if(bTryDirectPaint && drawAlphaBitmap(rPosAry, rSSalBitmap, rSTransparentBitmap))
541 {
542 return;
543 }
544
545 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
546 const WinSalBitmap& rTransparentBitmap = static_cast<const WinSalBitmap&>(rSTransparentBitmap);
547
548 SalTwoRect aPosAry = rPosAry;
549 int nDstX = (int)aPosAry.mnDestX;
550 int nDstY = (int)aPosAry.mnDestY;
551 int nDstWidth = (int)aPosAry.mnDestWidth;
552 int nDstHeight = (int)aPosAry.mnDestHeight;
553 HDC hDC = getHDC();
554 HBITMAP hMemBitmap = 0;
555 HBITMAP hMaskBitmap = 0;
556
557 if( ( nDstWidth > CACHED_HDC_DEFEXT ) || ( nDstHeight > CACHED_HDC_DEFEXT ) )
558 {
559 hMemBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight );
560 hMaskBitmap = CreateCompatibleBitmap( hDC, nDstWidth, nDstHeight );
561 }
562
563 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, hMemBitmap );
564 HDC hMaskDC = ImplGetCachedDC( CACHED_HDC_2, hMaskBitmap );
565
566 aPosAry.mnDestX = aPosAry.mnDestY = 0;
567 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hDC, nDstX, nDstY, SRCCOPY );
568
569 // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem,
570 // die Farben der Maske richtig auf die Palette abzubilden,
571 // wenn wir die DIB direkt ausgeben => DDB-Ausgabe
572 if( ( GetBitCount() <= 8 ) && rTransparentBitmap.ImplGethDIB() && rTransparentBitmap.GetBitCount() == 1 )
573 {
574 WinSalBitmap aTmp;
575
576 if( aTmp.Create( rTransparentBitmap, this ) )
577 ImplDrawBitmap( hMaskDC, aPosAry, aTmp, FALSE, SRCCOPY );
578 }
579 else
580 ImplDrawBitmap( hMaskDC, aPosAry, rTransparentBitmap, FALSE, SRCCOPY );
581
582 // now MemDC contains background, MaskDC the transparency mask
583
584 // #105055# Respect XOR mode
585 if( mbXORMode )
586 {
587 ImplDrawBitmap( hMaskDC, aPosAry, rSalBitmap, FALSE, SRCERASE );
588 // now MaskDC contains the bitmap area with black background
589 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCINVERT );
590 // now MemDC contains background XORed bitmap area ontop
591 }
592 else
593 {
594 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCAND );
595 // now MemDC contains background with masked-out bitmap area
596 ImplDrawBitmap( hMaskDC, aPosAry, rSalBitmap, FALSE, SRCERASE );
597 // now MaskDC contains the bitmap area with black background
598 BitBlt( hMemDC, 0, 0, nDstWidth, nDstHeight, hMaskDC, 0, 0, SRCPAINT );
599 // now MemDC contains background and bitmap merged together
600 }
601 // copy to output DC
602 BitBlt( hDC, nDstX, nDstY, nDstWidth, nDstHeight, hMemDC, 0, 0, SRCCOPY );
603
604 ImplReleaseCachedDC( CACHED_HDC_1 );
605 ImplReleaseCachedDC( CACHED_HDC_2 );
606
607 // hMemBitmap != 0 ==> hMaskBitmap != 0
608 if( hMemBitmap )
609 {
610 DeleteObject( hMemBitmap );
611 DeleteObject( hMaskBitmap );
612 }
613 }
614
615 // -----------------------------------------------------------------------
616
drawAlphaRect(long nX,long nY,long nWidth,long nHeight,sal_uInt8 nTransparency)617 bool WinSalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
618 long nHeight, sal_uInt8 nTransparency )
619 {
620 if( mbPen || !mbBrush || mbXORMode )
621 return false; // can only perform solid fills without XOR.
622
623 HDC hMemDC = ImplGetCachedDC( CACHED_HDC_1, 0 );
624 SetPixel( hMemDC, (int)0, (int)0, mnBrushColor );
625
626 BLENDFUNCTION aFunc = {
627 AC_SRC_OVER,
628 0,
629 255 - 255L*nTransparency/100,
630 0
631 };
632
633 // hMemDC contains a 1x1 bitmap of the right color - stretch-blit
634 // that to dest hdc
635 bool bRet = AlphaBlend( getHDC(), nX, nY, nWidth, nHeight,
636 hMemDC, 0,0,1,1,
637 aFunc ) == TRUE;
638
639 ImplReleaseCachedDC( CACHED_HDC_1 );
640
641 return bRet;
642 }
643
644 // -----------------------------------------------------------------------
645
drawMask(const SalTwoRect & rPosAry,const SalBitmap & rSSalBitmap,SalColor nMaskColor)646 void WinSalGraphics::drawMask( const SalTwoRect& rPosAry,
647 const SalBitmap& rSSalBitmap,
648 SalColor nMaskColor )
649 {
650 DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
651
652 const WinSalBitmap& rSalBitmap = static_cast<const WinSalBitmap&>(rSSalBitmap);
653
654 SalTwoRect aPosAry = rPosAry;
655 const BYTE cRed = SALCOLOR_RED( nMaskColor );
656 const BYTE cGreen = SALCOLOR_GREEN( nMaskColor );
657 const BYTE cBlue = SALCOLOR_BLUE( nMaskColor );
658 HDC hDC = getHDC();
659 HBRUSH hMaskBrush = CreateSolidBrush( RGB( cRed, cGreen, cBlue ) );
660 HBRUSH hOldBrush = SelectBrush( hDC, hMaskBrush );
661
662 // bei Paletten-Displays hat WIN/WNT offenbar ein kleines Problem,
663 // die Farben der Maske richtig auf die Palette abzubilden,
664 // wenn wir die DIB direkt ausgeben => DDB-Ausgabe
665 if( ( GetBitCount() <= 8 ) && rSalBitmap.ImplGethDIB() && rSalBitmap.GetBitCount() == 1 )
666 {
667 WinSalBitmap aTmp;
668
669 if( aTmp.Create( rSalBitmap, this ) )
670 ImplDrawBitmap( hDC, aPosAry, aTmp, FALSE, 0x00B8074AUL );
671 }
672 else
673 ImplDrawBitmap( hDC, aPosAry, rSalBitmap, FALSE, 0x00B8074AUL );
674
675 SelectBrush( hDC, hOldBrush );
676 DeleteBrush( hMaskBrush );
677 }
678
679 // -----------------------------------------------------------------------
680
getBitmap(long nX,long nY,long nDX,long nDY)681 SalBitmap* WinSalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
682 {
683 DBG_ASSERT( !mbPrinter, "No ::GetBitmap() from printer possible!" );
684
685 WinSalBitmap* pSalBitmap = NULL;
686
687 nDX = labs( nDX );
688 nDY = labs( nDY );
689
690 HDC hDC = getHDC();
691 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY );
692 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap );
693 sal_Bool bRet;
694 DWORD err = 0;
695
696 bRet = BitBlt( hBmpDC, 0, 0, (int) nDX, (int) nDY, hDC, (int) nX, (int) nY, SRCCOPY ) ? TRUE : FALSE;
697 ImplReleaseCachedDC( CACHED_HDC_1 );
698
699 if( bRet )
700 {
701 pSalBitmap = new WinSalBitmap;
702
703 if( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) )
704 {
705 delete pSalBitmap;
706 pSalBitmap = NULL;
707 }
708 }
709 else
710 {
711 err = GetLastError();
712 // #124826# avoid resource leak ! happens when runing without desktop access (remote desktop, service, may be screensavers)
713 DeleteBitmap( hBmpBitmap );
714 }
715
716 return pSalBitmap;
717 }
718
719 // -----------------------------------------------------------------------
720
getPixel(long nX,long nY)721 SalColor WinSalGraphics::getPixel( long nX, long nY )
722 {
723 COLORREF aWinCol = ::GetPixel( getHDC(), (int) nX, (int) nY );
724
725 if ( CLR_INVALID == aWinCol )
726 return MAKE_SALCOLOR( 0, 0, 0 );
727 else
728 return MAKE_SALCOLOR( GetRValue( aWinCol ),
729 GetGValue( aWinCol ),
730 GetBValue( aWinCol ) );
731 }
732
733 // -----------------------------------------------------------------------
734
invert(long nX,long nY,long nWidth,long nHeight,SalInvert nFlags)735 void WinSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags )
736 {
737 if ( nFlags & SAL_INVERT_TRACKFRAME )
738 {
739 HPEN hDotPen = CreatePen( PS_DOT, 0, 0 );
740 HPEN hOldPen = SelectPen( getHDC(), hDotPen );
741 HBRUSH hOldBrush = SelectBrush( getHDC(), GetStockBrush( NULL_BRUSH ) );
742 int nOldROP = SetROP2( getHDC(), R2_NOT );
743
744 WIN_Rectangle( getHDC(), (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) );
745
746 SetROP2( getHDC(), nOldROP );
747 SelectPen( getHDC(), hOldPen );
748 SelectBrush( getHDC(), hOldBrush );
749 DeletePen( hDotPen );
750 }
751 else if ( nFlags & SAL_INVERT_50 )
752 {
753 SalData* pSalData = GetSalData();
754 if ( !pSalData->mh50Brush )
755 {
756 if ( !pSalData->mh50Bmp )
757 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 );
758 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp );
759 }
760
761 COLORREF nOldTextColor = ::SetTextColor( getHDC(), 0 );
762 HBRUSH hOldBrush = SelectBrush( getHDC(), pSalData->mh50Brush );
763 PatBlt( getHDC(), nX, nY, nWidth, nHeight, PATINVERT );
764 ::SetTextColor( getHDC(), nOldTextColor );
765 SelectBrush( getHDC(), hOldBrush );
766 }
767 else
768 {
769 RECT aRect;
770 aRect.left = (int)nX;
771 aRect.top = (int)nY;
772 aRect.right = (int)nX+nWidth;
773 aRect.bottom = (int)nY+nHeight;
774 ::InvertRect( getHDC(), &aRect );
775 }
776 }
777
778 // -----------------------------------------------------------------------
779
invert(sal_uInt32 nPoints,const SalPoint * pPtAry,SalInvert nSalFlags)780 void WinSalGraphics::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nSalFlags )
781 {
782 HPEN hPen;
783 HPEN hOldPen;
784 HBRUSH hBrush;
785 HBRUSH hOldBrush = 0;
786 COLORREF nOldTextColor RGB(0,0,0);
787 int nOldROP = SetROP2( getHDC(), R2_NOT );
788
789 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
790 hPen = CreatePen( PS_DOT, 0, 0 );
791 else
792 {
793
794 if ( nSalFlags & SAL_INVERT_50 )
795 {
796 SalData* pSalData = GetSalData();
797 if ( !pSalData->mh50Brush )
798 {
799 if ( !pSalData->mh50Bmp )
800 pSalData->mh50Bmp = ImplLoadSalBitmap( SAL_RESID_BITMAP_50 );
801 pSalData->mh50Brush = CreatePatternBrush( pSalData->mh50Bmp );
802 }
803
804 hBrush = pSalData->mh50Brush;
805 }
806 else
807 hBrush = GetStockBrush( BLACK_BRUSH );
808
809 hPen = GetStockPen( NULL_PEN );
810 nOldTextColor = ::SetTextColor( getHDC(), 0 );
811 hOldBrush = SelectBrush( getHDC(), hBrush );
812 }
813 hOldPen = SelectPen( getHDC(), hPen );
814
815 POINT* pWinPtAry;
816 // Unter NT koennen wir das Array direkt weiterreichen
817 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
818 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
819
820 pWinPtAry = (POINT*)pPtAry;
821 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
822 // von Punkten
823 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
824 {
825 if ( !Polyline( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
826 Polyline( getHDC(), pWinPtAry, MAX_64KSALPOINTS );
827 }
828 else
829 {
830 if ( !WIN_Polygon( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
831 WIN_Polygon( getHDC(), pWinPtAry, MAX_64KSALPOINTS );
832 }
833
834 SetROP2( getHDC(), nOldROP );
835 SelectPen( getHDC(), hOldPen );
836
837 if ( nSalFlags & SAL_INVERT_TRACKFRAME )
838 DeletePen( hPen );
839 else
840 {
841 ::SetTextColor( getHDC(), nOldTextColor );
842 SelectBrush( getHDC(), hOldBrush );
843 }
844 }
845