merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / gdi / outdev6.cxx
blobcf20a29208b4004a35e89593c0d48d4d36bfe8b8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: outdev6.cxx,v $
10 * $Revision: 1.33.16.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #ifndef _SV_SVSYS_HXX
35 #include <svsys.h>
36 #endif
37 #include <vcl/salgdi.hxx>
38 #include <tools/debug.hxx>
39 #include <vcl/outdev.h>
40 #include <vcl/outdev.hxx>
41 #include <vcl/virdev.hxx>
42 #include <vcl/bmpacc.hxx>
43 #include <vcl/metaact.hxx>
44 #include <vcl/gdimtf.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/wrkwin.hxx>
47 #include <vcl/graph.hxx>
48 #include <vcl/wall2.hxx>
49 #include <com/sun/star/uno/Sequence.hxx>
51 #include <basegfx/vector/b2dvector.hxx>
52 #include <basegfx/polygon/b2dpolypolygon.hxx>
53 #include <basegfx/polygon/b2dpolygon.hxx>
54 #include <basegfx/matrix/b2dhommatrix.hxx>
55 #include <math.h>
56 #include <vcl/window.h>
57 #include <vcl/svdata.hxx>
59 // ========================================================================
61 DBG_NAMEEX( OutputDevice )
63 // ------------------------------------------------------------------------
65 void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, ULONG nFlags )
67 DBG_TRACE( "OutputDevice::DrawGrid()" );
68 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
70 Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
71 aDstRect.Intersection( rRect );
73 if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
74 return;
76 if( !mpGraphics && !ImplGetGraphics() )
77 return;
79 if( mbInitClipRegion )
80 ImplInitClipRegion();
82 if( mbOutputClipped )
83 return;
85 const long nDistX = Max( rDist.Width(), 1L );
86 const long nDistY = Max( rDist.Height(), 1L );
87 long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
88 long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
89 const long nRight = aDstRect.Right();
90 const long nBottom = aDstRect.Bottom();
91 const long nStartX = ImplLogicXToDevicePixel( nX );
92 const long nEndX = ImplLogicXToDevicePixel( nRight );
93 const long nStartY = ImplLogicYToDevicePixel( nY );
94 const long nEndY = ImplLogicYToDevicePixel( nBottom );
95 long nHorzCount = 0L;
96 long nVertCount = 0L;
98 ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
99 ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
101 if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
103 aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
104 aVertBuf[ nVertCount++ ] = nStartY;
105 while( ( nY += nDistY ) <= nBottom )
106 aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
109 if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
111 aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
112 aHorzBuf[ nHorzCount++ ] = nStartX;
113 while( ( nX += nDistX ) <= nRight )
114 aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
117 if( mbInitLineColor )
118 ImplInitLineColor();
120 if( mbInitFillColor )
121 ImplInitFillColor();
123 const BOOL bOldMap = mbMap;
124 EnableMapMode( FALSE );
126 if( nFlags & GRID_DOTS )
128 for( long i = 0L; i < nVertCount; i++ )
129 for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
130 mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
132 else
134 if( nFlags & GRID_HORZLINES )
136 for( long i = 0L; i < nVertCount; i++ )
138 nY = aVertBuf[ i ];
139 mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
143 if( nFlags & GRID_VERTLINES )
145 for( long i = 0L; i < nHorzCount; i++ )
147 nX = aHorzBuf[ i ];
148 mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
153 EnableMapMode( bOldMap );
155 if( mpAlphaVDev )
156 mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
159 // ------------------------------------------------------------------------
160 // Caution: This method is nearly the same as
161 // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
162 // so when changes are made here do not forget to make change sthere, too
164 void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
166 DBG_TRACE( "OutputDevice::DrawTransparent(B2D&,transparency)" );
167 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
169 // AW: Do NOT paint empty PolyPolygons
170 if(!rB2DPolyPoly.count())
171 return;
173 // we need a graphics
174 if( !mpGraphics )
175 if( !ImplGetGraphics() )
176 return;
178 if( mbInitClipRegion )
179 ImplInitClipRegion();
180 if( mbOutputClipped )
181 return;
183 if( mbInitLineColor )
184 ImplInitLineColor();
185 if( mbInitFillColor )
186 ImplInitFillColor();
188 if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
189 && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
190 && ROP_OVERPAINT == GetRasterOp()
191 && IsFillColor())
193 // b2dpolygon support not implemented yet on non-UNX platforms
194 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
195 basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
197 // transform the polygon and ensure closed
198 aB2DPolyPolygon.transform(aTransform);
199 aB2DPolyPolygon.setClosed(true);
201 if(mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, fTransparency, this))
203 #if 0
204 // MetaB2DPolyPolygonAction is not implemented yet:
205 // according to AW adding it is very dangerous since there is a lot
206 // of code that uses the metafile actions directly and unless every
207 // place that does this knows about the new action we need to fallback
208 if( mpMetaFile )
209 mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) );
210 #else
211 if( mpMetaFile )
212 mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0)));
213 #endif
214 return;
218 // fallback to old polygon drawing if needed
219 const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly );
220 DrawTransparent(PolyPolygon(rB2DPolyPoly), static_cast< sal_uInt16 >(fTransparency * 100.0));
223 // ------------------------------------------------------------------------
225 void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
226 USHORT nTransparencePercent )
228 DBG_TRACE( "OutputDevice::DrawTransparent()" );
229 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
231 // short circuit for drawing an opaque polygon
232 if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) )
234 DrawPolyPolygon( rPolyPoly );
235 return;
238 // short circut for drawing an invisible polygon
239 if( !mbFillColor || (nTransparencePercent >= 100) )
241 // short circuit if the polygon border is invisible too
242 if( !mbLineColor )
243 return;
245 // DrawTransparent() assumes that the border is NOT to be drawn transparently???
246 Push( PUSH_FILLCOLOR );
247 SetFillColor();
248 DrawPolyPolygon( rPolyPoly );
249 Pop();
250 return;
253 // handle metafile recording
254 if( mpMetaFile )
255 mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
257 bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
258 if( bDrawn )
259 return;
261 // get the device graphics as drawing target
262 if( !mpGraphics )
263 if( !ImplGetGraphics() )
264 return;
266 // debug helper:
267 static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
269 // try hard to draw it directly, because the emulation layers are slower
270 if( !pDisableNative
271 && mpGraphics->supportsOperation( OutDevSupport_B2DDraw )
272 #ifdef WIN32
273 // workaround bad dithering on remote displaying when using GDI+ with toolbar buttoin hilighting
274 && !rPolyPoly.IsRect()
275 #endif
278 // prepare the graphics device
279 if( mbInitClipRegion )
280 ImplInitClipRegion();
281 if( mbOutputClipped )
282 return;
283 if( mbInitLineColor )
284 ImplInitLineColor();
285 if( mbInitFillColor )
286 ImplInitFillColor();
288 // get the polygon in device coordinates
289 basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
290 aB2DPolyPolygon.setClosed( true );
291 const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
292 aB2DPolyPolygon.transform( aTransform );
294 // draw the transparent polygon
295 bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, nTransparencePercent*0.01, this );
297 // DrawTransparent() assumes that the border is NOT to be drawn transparently???
298 if( mbLineColor )
300 // disable the fill color for now
301 mpGraphics->SetFillColor();
302 // draw the border line
303 const basegfx::B2DVector aLineWidths( 1, 1 );
304 const int nPolyCount = aB2DPolyPolygon.count();
305 for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
307 const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
308 mpGraphics->DrawPolyLine( rPolygon, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, this );
310 // prepare to restore the fill color
311 mbInitFillColor = mbFillColor;
315 if( bDrawn )
316 return;
318 if( 1 )
320 VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
322 // #110958# Disable alpha VDev, we perform the necessary
323 // operation explicitely further below.
324 if( mpAlphaVDev )
325 mpAlphaVDev = NULL;
327 GDIMetaFile* pOldMetaFile = mpMetaFile;
328 mpMetaFile = NULL;
330 if( OUTDEV_PRINTER == meOutDevType )
332 Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() );
333 const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) );
334 const long nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L );
335 long nMove;
336 const USHORT nTrans = ( nTransparencePercent < 13 ) ? 0 :
337 ( nTransparencePercent < 38 ) ? 25 :
338 ( nTransparencePercent < 63 ) ? 50 :
339 ( nTransparencePercent < 88 ) ? 75 : 100;
341 switch( nTrans )
343 case( 25 ): nMove = nBaseExtent * 3; break;
344 case( 50 ): nMove = nBaseExtent * 4; break;
345 case( 75 ): nMove = nBaseExtent * 6; break;
346 // TODO What is the correct VALUE???
347 default: nMove = 0; break;
350 Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
351 IntersectClipRegion( rPolyPoly );
352 SetLineColor( GetFillColor() );
354 Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
356 const BOOL bOldMap = mbMap;
357 EnableMapMode( FALSE );
359 while( aRect.Top() <= aPolyRect.Bottom() )
361 DrawRect( aRect );
362 aRect.Move( 0, nMove );
365 aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
366 while( aRect.Left() <= aPolyRect.Right() )
368 DrawRect( aRect );
369 aRect.Move( nMove, 0 );
372 EnableMapMode( bOldMap );
373 Pop();
375 else
377 PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
378 Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
379 Point aPoint;
380 Rectangle aDstRect( aPoint, GetOutputSizePixel() );
382 aDstRect.Intersection( aPolyRect );
384 if( OUTDEV_WINDOW == meOutDevType )
386 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
388 if( !aPaintRgn.IsNull() )
389 aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
392 if( !aDstRect.IsEmpty() )
394 // #i66849# Added fast path for exactly rectangular
395 // polygons
396 // #i83087# Naturally, system alpha blending cannot
397 // work with separate alpha VDev
398 if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() )
400 // setup Graphics only here (other cases delegate
401 // to basic OutDev methods)
402 if( 1 )
404 if ( mbInitClipRegion )
405 ImplInitClipRegion();
406 if ( mbInitLineColor )
407 ImplInitLineColor();
408 if ( mbInitFillColor )
409 ImplInitFillColor();
411 Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
412 Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
414 if( !mbOutputClipped )
416 bDrawn = mpGraphics->DrawAlphaRect(
417 aPixelRect.Left(), aPixelRect.Top(),
418 // #i98405# use methods with small g, else one pixel too much will be painted.
419 // This is because the source is a polygon which when painted would not paint
420 // the rightmost and lowest pixel line(s), so use one pixel less for the
421 // rectangle, too.
422 aPixelRect.getWidth(), aPixelRect.getHeight(),
423 sal::static_int_cast<sal_uInt8>(nTransparencePercent),
424 this );
426 else
427 bDrawn = true;
431 if( !bDrawn )
433 VirtualDevice aVDev( *this, 1 );
434 const Size aDstSz( aDstRect.GetSize() );
435 const BYTE cTrans = (BYTE) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
437 if( aDstRect.Left() || aDstRect.Top() )
438 aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
440 if( aVDev.SetOutputSizePixel( aDstSz ) )
442 const BOOL bOldMap = mbMap;
444 EnableMapMode( FALSE );
446 aVDev.SetLineColor( COL_BLACK );
447 aVDev.SetFillColor( COL_BLACK );
448 aVDev.DrawPolyPolygon( aPolyPoly );
450 Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
451 Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
453 // #107766# check for non-empty bitmaps before accessing them
454 if( !!aPaint && !!aPolyMask )
456 BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
457 BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
459 if( pW && pR )
461 BitmapColor aPixCol;
462 const BitmapColor aFillCol( GetFillColor() );
463 const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
464 const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
465 const long nWidth = pW->Width(), nHeight = pW->Height();
466 const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
467 long nX, nY;
469 if( aPaint.GetBitCount() <= 8 )
471 const BitmapPalette& rPal = pW->GetPalette();
472 const USHORT nCount = rPal.GetEntryCount();
473 BitmapColor* pMap = (BitmapColor*) new BYTE[ nCount * sizeof( BitmapColor ) ];
475 for( USHORT i = 0; i < nCount; i++ )
477 BitmapColor aCol( rPal[ i ] );
478 pMap[ i ] = BitmapColor( (BYTE) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
481 if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
482 pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
484 const BYTE cBlack = aBlack.GetIndex();
486 for( nY = 0; nY < nHeight; nY++ )
488 Scanline pWScan = pW->GetScanline( nY );
489 Scanline pRScan = pR->GetScanline( nY );
490 BYTE cBit = 128;
492 for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
494 if( !cBit )
495 cBit = 128, pRScan++;
497 if( ( *pRScan & cBit ) == cBlack )
498 *pWScan = (BYTE) pMap[ *pWScan ].GetIndex();
502 else
504 for( nY = 0; nY < nHeight; nY++ )
505 for( nX = 0; nX < nWidth; nX++ )
506 if( pR->GetPixel( nY, nX ) == aBlack )
507 pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
510 delete[] (BYTE*) pMap;
512 else
514 if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
515 pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
517 const BYTE cBlack = aBlack.GetIndex();
519 for( nY = 0; nY < nHeight; nY++ )
521 Scanline pWScan = pW->GetScanline( nY );
522 Scanline pRScan = pR->GetScanline( nY );
523 BYTE cBit = 128;
525 for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
527 if( !cBit )
528 cBit = 128, pRScan++;
530 if( ( *pRScan & cBit ) == cBlack )
532 pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
533 pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
534 pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
539 else
541 for( nY = 0; nY < nHeight; nY++ )
543 for( nX = 0; nX < nWidth; nX++ )
545 if( pR->GetPixel( nY, nX ) == aBlack )
547 aPixCol = pW->GetColor( nY, nX );
548 pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
556 aPolyMask.ReleaseAccess( pR );
557 aPaint.ReleaseAccess( pW );
559 DrawBitmap( aDstRect.TopLeft(), aPaint );
561 EnableMapMode( bOldMap );
563 if( mbLineColor )
565 Push( PUSH_FILLCOLOR );
566 SetFillColor();
567 DrawPolyPolygon( rPolyPoly );
568 Pop();
572 else
573 DrawPolyPolygon( rPolyPoly );
578 mpMetaFile = pOldMetaFile;
580 // #110958# Restore disabled alpha VDev
581 mpAlphaVDev = pOldAlphaVDev;
583 // #110958# Apply alpha value also to VDev alpha channel
584 if( mpAlphaVDev )
586 const Color aFillCol( mpAlphaVDev->GetFillColor() );
587 mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<UINT8>(255*nTransparencePercent/100),
588 sal::static_int_cast<UINT8>(255*nTransparencePercent/100),
589 sal::static_int_cast<UINT8>(255*nTransparencePercent/100)) );
591 mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
593 mpAlphaVDev->SetFillColor( aFillCol );
598 // -----------------------------------------------------------------------
600 void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
601 const Size& rSize, const Gradient& rTransparenceGradient )
603 DBG_TRACE( "OutputDevice::DrawTransparent()" );
604 DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
606 const Color aBlack( COL_BLACK );
608 if( mpMetaFile )
609 mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
611 if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
612 ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
614 ( (GDIMetaFile&) rMtf ).WindStart();
615 ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
616 ( (GDIMetaFile&) rMtf ).WindStart();
618 else
620 GDIMetaFile* pOldMetaFile = mpMetaFile;
621 Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
622 Point aPoint;
623 Rectangle aDstRect( aPoint, GetOutputSizePixel() );
625 mpMetaFile = NULL;
626 aDstRect.Intersection( aOutRect );
628 if( OUTDEV_WINDOW == meOutDevType )
630 const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
632 if( !aPaintRgn.IsNull() )
633 aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
636 if( !aDstRect.IsEmpty() )
638 VirtualDevice* pVDev = new VirtualDevice;
640 ((OutputDevice*)pVDev)->mnDPIX = mnDPIX;
641 ((OutputDevice*)pVDev)->mnDPIY = mnDPIY;
643 if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
645 if(GetAntialiasing())
647 // #i102109#
648 // For MetaFile replay (see task) it may now be neccessary to take
649 // into account that the content is AntiAlialised and needs to be masked
650 // like that. Instead of masking, i will use a copy-modify-paste cycle
651 // here (as i already use in the VclPrimiziveRenderer with successs)
652 pVDev->SetAntialiasing(GetAntialiasing());
654 // create MapMode for buffer (offset needed) and set
655 MapMode aMap(GetMapMode());
656 const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
657 aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
658 pVDev->SetMapMode(aMap);
660 // copy MapMode state and disable for target
661 const bool bOrigMapModeEnabled(IsMapModeEnabled());
662 EnableMapMode(false);
664 // copy MapMode state and disable for buffer
665 const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled());
666 pVDev->EnableMapMode(false);
668 // copy content from original to buffer
669 pVDev->DrawOutDev(
670 aPoint, pVDev->GetOutputSizePixel(), // dest
671 aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source
672 *this);
674 // draw MetaFile to buffer
675 pVDev->EnableMapMode(bBufferMapModeEnabled);
676 ((GDIMetaFile&)rMtf).WindStart();
677 ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize);
678 ((GDIMetaFile&)rMtf).WindStart();
680 // get content bitmap from buffer
681 pVDev->EnableMapMode(false);
682 const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
684 // create alpha mask from gradient and get as Bitmap
685 pVDev->EnableMapMode(bBufferMapModeEnabled);
686 pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT);
687 pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient);
688 pVDev->SetDrawMode(DRAWMODE_DEFAULT);
689 pVDev->EnableMapMode(false);
690 const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
692 // draw masked content to target and restore MapMode
693 DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
694 EnableMapMode(bOrigMapModeEnabled);
696 else
698 Bitmap aPaint, aMask;
699 AlphaMask aAlpha;
700 MapMode aMap( GetMapMode() );
701 Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
702 const BOOL bOldMap = mbMap;
704 aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
705 pVDev->SetMapMode( aMap );
706 const BOOL bVDevOldMap = pVDev->IsMapModeEnabled();
708 // create paint bitmap
709 ( (GDIMetaFile&) rMtf ).WindStart();
710 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
711 ( (GDIMetaFile&) rMtf ).WindStart();
712 pVDev->EnableMapMode( FALSE );
713 aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
714 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( TRUE ) here!
716 // create mask bitmap
717 pVDev->SetLineColor( COL_BLACK );
718 pVDev->SetFillColor( COL_BLACK );
719 pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
720 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
721 DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
722 ( (GDIMetaFile&) rMtf ).WindStart();
723 ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
724 ( (GDIMetaFile&) rMtf ).WindStart();
725 pVDev->EnableMapMode( FALSE );
726 aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
727 pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( TRUE ) here!
729 // create alpha mask from gradient
730 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
731 pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
732 pVDev->SetDrawMode( DRAWMODE_DEFAULT );
733 pVDev->EnableMapMode( FALSE );
734 pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
736 aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
738 delete pVDev;
740 EnableMapMode( FALSE );
741 DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
742 EnableMapMode( bOldMap );
745 else
746 delete pVDev;
749 mpMetaFile = pOldMetaFile;
753 // -----------------------------------------------------------------------
755 void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
756 long nWidth, long nHeight,
757 const Wallpaper& rWallpaper )
759 // Wallpaper ohne Umrandung zeichnen
760 Color aOldLineColor = GetLineColor();
761 Color aOldFillColor = GetFillColor();
762 SetLineColor();
763 SetFillColor( rWallpaper.GetColor() );
764 BOOL bMap = mbMap;
765 EnableMapMode( FALSE );
766 DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
767 SetLineColor( aOldLineColor );
768 SetFillColor( aOldFillColor );
769 EnableMapMode( bMap );
772 // -----------------------------------------------------------------------
774 void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
775 long nWidth, long nHeight,
776 const Wallpaper& rWallpaper )
778 BitmapEx aBmpEx;
779 const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
780 Point aPos;
781 Size aSize;
782 GDIMetaFile* pOldMetaFile = mpMetaFile;
783 const WallpaperStyle eStyle = rWallpaper.GetStyle();
784 const BOOL bOldMap = mbMap;
785 BOOL bDrawn = FALSE;
786 BOOL bDrawGradientBackground = FALSE;
787 BOOL bDrawColorBackground = FALSE;
789 if( pCached )
790 aBmpEx = *pCached;
791 else
792 aBmpEx = rWallpaper.GetBitmap();
794 const long nBmpWidth = aBmpEx.GetSizePixel().Width();
795 const long nBmpHeight = aBmpEx.GetSizePixel().Height();
796 const BOOL bTransparent = aBmpEx.IsTransparent();
798 // draw background
799 if( bTransparent )
801 if( rWallpaper.IsGradient() )
802 bDrawGradientBackground = TRUE;
803 else
805 if( !pCached && !rWallpaper.GetColor().GetTransparency() )
807 VirtualDevice aVDev( *this );
808 aVDev.SetBackground( rWallpaper.GetColor() );
809 aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
810 aVDev.DrawBitmapEx( Point(), aBmpEx );
811 aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
814 bDrawColorBackground = TRUE;
817 else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
819 if( rWallpaper.IsGradient() )
820 bDrawGradientBackground = TRUE;
821 else
822 bDrawColorBackground = TRUE;
825 // background of bitmap?
826 if( bDrawGradientBackground )
827 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
828 else if( bDrawColorBackground && bTransparent )
830 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
831 bDrawColorBackground = FALSE;
834 // calc pos and size
835 if( rWallpaper.IsRect() )
837 const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
838 aPos = aBound.TopLeft();
839 aSize = aBound.GetSize();
841 else
843 aPos = Point( nX, nY );
844 aSize = Size( nWidth, nHeight );
847 mpMetaFile = NULL;
848 EnableMapMode( FALSE );
849 Push( PUSH_CLIPREGION );
850 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
852 switch( eStyle )
854 case( WALLPAPER_SCALE ):
856 if( !pCached || ( pCached->GetSizePixel() != aSize ) )
858 if( pCached )
859 rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
861 aBmpEx = rWallpaper.GetBitmap();
862 aBmpEx.Scale( aSize );
863 aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
866 break;
868 case( WALLPAPER_TOPLEFT ):
869 break;
871 case( WALLPAPER_TOP ):
872 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
873 break;
875 case( WALLPAPER_TOPRIGHT ):
876 aPos.X() += ( aSize.Width() - nBmpWidth );
877 break;
879 case( WALLPAPER_LEFT ):
880 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
881 break;
883 case( WALLPAPER_CENTER ):
885 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
886 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
888 break;
890 case( WALLPAPER_RIGHT ):
892 aPos.X() += ( aSize.Width() - nBmpWidth );
893 aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
895 break;
897 case( WALLPAPER_BOTTOMLEFT ):
898 aPos.Y() += ( aSize.Height() - nBmpHeight );
899 break;
901 case( WALLPAPER_BOTTOM ):
903 aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
904 aPos.Y() += ( aSize.Height() - nBmpHeight );
906 break;
908 case( WALLPAPER_BOTTOMRIGHT ):
910 aPos.X() += ( aSize.Width() - nBmpWidth );
911 aPos.Y() += ( aSize.Height() - nBmpHeight );
913 break;
915 default:
917 const long nRight = nX + nWidth - 1L;
918 const long nBottom = nY + nHeight - 1L;
919 long nFirstX;
920 long nFirstY;
922 if( eStyle == WALLPAPER_TILE )
924 nFirstX = aPos.X();
925 nFirstY = aPos.Y();
927 else
929 nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
930 nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
933 const long nOffX = ( nFirstX - nX ) % nBmpWidth;
934 const long nOffY = ( nFirstY - nY ) % nBmpHeight;
935 long nStartX = nX + nOffX;
936 long nStartY = nY + nOffY;
938 if( nOffX > 0L )
939 nStartX -= nBmpWidth;
941 if( nOffY > 0L )
942 nStartY -= nBmpHeight;
944 for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
945 for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
946 DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
948 bDrawn = TRUE;
950 break;
953 if( !bDrawn )
955 // optimized for non-transparent bitmaps
956 if( bDrawColorBackground )
958 const Size aBmpSize( aBmpEx.GetSizePixel() );
959 const Point aTmpPoint;
960 const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
961 const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
962 Rectangle aWorkRect;
964 aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
965 aWorkRect.Justify();
966 aWorkRect.Intersection( aColRect );
967 if( !aWorkRect.IsEmpty() )
969 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
970 aWorkRect.GetWidth(), aWorkRect.GetHeight(),
971 rWallpaper );
974 aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
975 aWorkRect.Justify();
976 aWorkRect.Intersection( aColRect );
977 if( !aWorkRect.IsEmpty() )
979 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
980 aWorkRect.GetWidth(), aWorkRect.GetHeight(),
981 rWallpaper );
984 aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
985 aWorkRect.Justify();
986 aWorkRect.Intersection( aColRect );
987 if( !aWorkRect.IsEmpty() )
989 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
990 aWorkRect.GetWidth(), aWorkRect.GetHeight(),
991 rWallpaper );
994 aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
995 aWorkRect.Justify();
996 aWorkRect.Intersection( aColRect );
997 if( !aWorkRect.IsEmpty() )
999 ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1000 aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1001 rWallpaper );
1005 DrawBitmapEx( aPos, aBmpEx );
1008 rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
1010 Pop();
1011 EnableMapMode( bOldMap );
1012 mpMetaFile = pOldMetaFile;
1015 // -----------------------------------------------------------------------
1017 void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
1018 long nWidth, long nHeight,
1019 const Wallpaper& rWallpaper )
1021 Rectangle aBound;
1022 GDIMetaFile* pOldMetaFile = mpMetaFile;
1023 const BOOL bOldMap = mbMap;
1024 BOOL bNeedGradient = TRUE;
1027 if ( rWallpaper.IsRect() )
1028 aBound = LogicToPixel( rWallpaper.GetRect() );
1029 else
1031 aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
1033 mpMetaFile = NULL;
1034 EnableMapMode( FALSE );
1035 Push( PUSH_CLIPREGION );
1036 IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
1038 if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT )
1040 Window *pWin = dynamic_cast< Window* >( this );
1041 if( pWin )
1043 // limit gradient to useful size, so that it still can be noticed
1044 // in maximized windows
1045 long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width();
1046 if( gradientWidth > 1024 )
1047 gradientWidth = 1024;
1048 if( mnOutOffX+nWidth > gradientWidth )
1049 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() );
1050 if( mnOutOffX > gradientWidth )
1051 bNeedGradient = FALSE;
1052 else
1053 aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) );
1057 if( bNeedGradient )
1058 DrawGradient( aBound, rWallpaper.GetGradient() );
1060 Pop();
1061 EnableMapMode( bOldMap );
1062 mpMetaFile = pOldMetaFile;
1065 // -----------------------------------------------------------------------
1067 void OutputDevice::ImplDrawWallpaper( long nX, long nY,
1068 long nWidth, long nHeight,
1069 const Wallpaper& rWallpaper )
1071 if( rWallpaper.IsBitmap() )
1072 ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1073 else if( rWallpaper.IsGradient() )
1074 ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1075 else
1076 ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1079 // -----------------------------------------------------------------------
1081 void OutputDevice::DrawWallpaper( const Rectangle& rRect,
1082 const Wallpaper& rWallpaper )
1084 if ( mpMetaFile )
1085 mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
1087 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1088 return;
1090 if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
1092 Rectangle aRect = LogicToPixel( rRect );
1093 aRect.Justify();
1095 if ( !aRect.IsEmpty() )
1097 ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
1098 rWallpaper );
1102 if( mpAlphaVDev )
1103 mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
1106 // -----------------------------------------------------------------------
1108 void OutputDevice::Erase()
1110 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1111 return;
1113 BOOL bNativeOK = FALSE;
1114 if( meOutDevType == OUTDEV_WINDOW )
1116 Window* pWindow = static_cast<Window*>(this);
1117 ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground;
1118 if( aCtrlPart != 0 && ! pWindow->IsControlBackground() )
1120 ImplControlValue aControlValue;
1121 Point aGcc3WorkaroundTemporary;
1122 Region aCtrlRegion( Rectangle( aGcc3WorkaroundTemporary, GetOutputSizePixel() ) );
1123 ControlState nState = 0;
1125 if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED;
1126 bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion,
1127 nState, aControlValue, rtl::OUString() );
1131 if ( mbBackground && ! bNativeOK )
1133 RasterOp eRasterOp = GetRasterOp();
1134 if ( eRasterOp != ROP_OVERPAINT )
1135 SetRasterOp( ROP_OVERPAINT );
1136 ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
1137 if ( eRasterOp != ROP_OVERPAINT )
1138 SetRasterOp( eRasterOp );
1141 if( mpAlphaVDev )
1142 mpAlphaVDev->Erase();
1145 // -----------------------------------------------------------------------
1147 void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect,
1148 const Color& rLeftTopColor,
1149 const Color& rRightBottomColor )
1151 SetFillColor( rLeftTopColor );
1152 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) );
1153 DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) );
1154 SetFillColor( rRightBottomColor );
1155 DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) );
1156 DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) );
1159 // -----------------------------------------------------------------------
1161 void OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
1162 const GfxLink& rGfxLink, GDIMetaFile* pSubst )
1164 if ( mpMetaFile )
1166 GDIMetaFile aSubst;
1168 if( pSubst )
1169 aSubst = *pSubst;
1171 mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
1174 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1175 return;
1177 if( mbOutputClipped )
1178 return;
1180 Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
1181 if( !aRect.IsEmpty() )
1183 // draw the real EPS graphics
1184 bool bDrawn = FALSE;
1185 if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
1187 if( !mpGraphics && !ImplGetGraphics() )
1188 return;
1190 if( mbInitClipRegion )
1191 ImplInitClipRegion();
1193 aRect.Justify();
1194 bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
1195 (BYTE*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this );
1198 // else draw the substitution graphics
1199 if( !bDrawn && pSubst )
1201 GDIMetaFile* pOldMetaFile = mpMetaFile;
1203 mpMetaFile = NULL;
1204 Graphic( *pSubst ).Draw( this, rPoint, rSize );
1205 mpMetaFile = pOldMetaFile;
1209 if( mpAlphaVDev )
1210 mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );