1*9f62ea84SAndrew Rist /************************************************************** 2*9f62ea84SAndrew Rist * 3*9f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*9f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*9f62ea84SAndrew Rist * distributed with this work for additional information 6*9f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*9f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*9f62ea84SAndrew Rist * "License"); you may not use this file except in compliance 9*9f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at 10*9f62ea84SAndrew Rist * 11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*9f62ea84SAndrew Rist * 13*9f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*9f62ea84SAndrew Rist * software distributed under the License is distributed on an 15*9f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*9f62ea84SAndrew Rist * KIND, either express or implied. See the License for the 17*9f62ea84SAndrew Rist * specific language governing permissions and limitations 18*9f62ea84SAndrew Rist * under the License. 19*9f62ea84SAndrew Rist * 20*9f62ea84SAndrew Rist *************************************************************/ 21*9f62ea84SAndrew Rist 22*9f62ea84SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_vcl.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <tools/debug.hxx> 28cdf0e10cSrcweir #include <vcl/outdev.hxx> 29cdf0e10cSrcweir #include <vcl/virdev.hxx> 30cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 31cdf0e10cSrcweir #include <vcl/metaact.hxx> 32cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 33cdf0e10cSrcweir #include <vcl/svapp.hxx> 34cdf0e10cSrcweir #include <vcl/wrkwin.hxx> 35cdf0e10cSrcweir #include <vcl/graph.hxx> 36cdf0e10cSrcweir #include <vcl/rendergraphicrasterizer.hxx> 37cdf0e10cSrcweir 38cdf0e10cSrcweir #include <wall2.hxx> 39cdf0e10cSrcweir #include <salgdi.hxx> 40cdf0e10cSrcweir #include <window.h> 41cdf0e10cSrcweir #include <svdata.hxx> 42cdf0e10cSrcweir #include <outdev.h> 43cdf0e10cSrcweir 44cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.hxx> 45cdf0e10cSrcweir 46cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx> 47cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx> 48cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 49cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 50cdf0e10cSrcweir 51cdf0e10cSrcweir #include <math.h> 52cdf0e10cSrcweir 53cdf0e10cSrcweir // ======================================================================== 54cdf0e10cSrcweir 55cdf0e10cSrcweir DBG_NAMEEX( OutputDevice ) 56cdf0e10cSrcweir 57cdf0e10cSrcweir // ------------------------------------------------------------------------ 58cdf0e10cSrcweir 59cdf0e10cSrcweir void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, sal_uLong nFlags ) 60cdf0e10cSrcweir { 61cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawGrid()" ); 62cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 63cdf0e10cSrcweir 64cdf0e10cSrcweir Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() ); 65cdf0e10cSrcweir aDstRect.Intersection( rRect ); 66cdf0e10cSrcweir 67cdf0e10cSrcweir if( aDstRect.IsEmpty() || ImplIsRecordLayout() ) 68cdf0e10cSrcweir return; 69cdf0e10cSrcweir 70cdf0e10cSrcweir if( !mpGraphics && !ImplGetGraphics() ) 71cdf0e10cSrcweir return; 72cdf0e10cSrcweir 73cdf0e10cSrcweir if( mbInitClipRegion ) 74cdf0e10cSrcweir ImplInitClipRegion(); 75cdf0e10cSrcweir 76cdf0e10cSrcweir if( mbOutputClipped ) 77cdf0e10cSrcweir return; 78cdf0e10cSrcweir 79cdf0e10cSrcweir const long nDistX = Max( rDist.Width(), 1L ); 80cdf0e10cSrcweir const long nDistY = Max( rDist.Height(), 1L ); 81cdf0e10cSrcweir long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX ); 82cdf0e10cSrcweir long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY ); 83cdf0e10cSrcweir const long nRight = aDstRect.Right(); 84cdf0e10cSrcweir const long nBottom = aDstRect.Bottom(); 85cdf0e10cSrcweir const long nStartX = ImplLogicXToDevicePixel( nX ); 86cdf0e10cSrcweir const long nEndX = ImplLogicXToDevicePixel( nRight ); 87cdf0e10cSrcweir const long nStartY = ImplLogicYToDevicePixel( nY ); 88cdf0e10cSrcweir const long nEndY = ImplLogicYToDevicePixel( nBottom ); 89cdf0e10cSrcweir long nHorzCount = 0L; 90cdf0e10cSrcweir long nVertCount = 0L; 91cdf0e10cSrcweir 92cdf0e10cSrcweir ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf; 93cdf0e10cSrcweir ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf; 94cdf0e10cSrcweir 95cdf0e10cSrcweir if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) ) 96cdf0e10cSrcweir { 97cdf0e10cSrcweir aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L ); 98cdf0e10cSrcweir aVertBuf[ nVertCount++ ] = nStartY; 99cdf0e10cSrcweir while( ( nY += nDistY ) <= nBottom ) 100cdf0e10cSrcweir aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY ); 101cdf0e10cSrcweir } 102cdf0e10cSrcweir 103cdf0e10cSrcweir if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) ) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L ); 106cdf0e10cSrcweir aHorzBuf[ nHorzCount++ ] = nStartX; 107cdf0e10cSrcweir while( ( nX += nDistX ) <= nRight ) 108cdf0e10cSrcweir aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX ); 109cdf0e10cSrcweir } 110cdf0e10cSrcweir 111cdf0e10cSrcweir if( mbInitLineColor ) 112cdf0e10cSrcweir ImplInitLineColor(); 113cdf0e10cSrcweir 114cdf0e10cSrcweir if( mbInitFillColor ) 115cdf0e10cSrcweir ImplInitFillColor(); 116cdf0e10cSrcweir 117cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 118cdf0e10cSrcweir EnableMapMode( sal_False ); 119cdf0e10cSrcweir 120cdf0e10cSrcweir if( nFlags & GRID_DOTS ) 121cdf0e10cSrcweir { 122cdf0e10cSrcweir for( long i = 0L; i < nVertCount; i++ ) 123cdf0e10cSrcweir for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ ) 124cdf0e10cSrcweir mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this ); 125cdf0e10cSrcweir } 126cdf0e10cSrcweir else 127cdf0e10cSrcweir { 128cdf0e10cSrcweir if( nFlags & GRID_HORZLINES ) 129cdf0e10cSrcweir { 130cdf0e10cSrcweir for( long i = 0L; i < nVertCount; i++ ) 131cdf0e10cSrcweir { 132cdf0e10cSrcweir nY = aVertBuf[ i ]; 133cdf0e10cSrcweir mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this ); 134cdf0e10cSrcweir } 135cdf0e10cSrcweir } 136cdf0e10cSrcweir 137cdf0e10cSrcweir if( nFlags & GRID_VERTLINES ) 138cdf0e10cSrcweir { 139cdf0e10cSrcweir for( long i = 0L; i < nHorzCount; i++ ) 140cdf0e10cSrcweir { 141cdf0e10cSrcweir nX = aHorzBuf[ i ]; 142cdf0e10cSrcweir mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this ); 143cdf0e10cSrcweir } 144cdf0e10cSrcweir } 145cdf0e10cSrcweir } 146cdf0e10cSrcweir 147cdf0e10cSrcweir EnableMapMode( bOldMap ); 148cdf0e10cSrcweir 149cdf0e10cSrcweir if( mpAlphaVDev ) 150cdf0e10cSrcweir mpAlphaVDev->DrawGrid( rRect, rDist, nFlags ); 151cdf0e10cSrcweir } 152cdf0e10cSrcweir 153cdf0e10cSrcweir // ------------------------------------------------------------------------ 154cdf0e10cSrcweir // Caution: This method is nearly the same as 155cdf0e10cSrcweir // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly ) 156cdf0e10cSrcweir // so when changes are made here do not forget to make change sthere, too 157cdf0e10cSrcweir 158cdf0e10cSrcweir void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawTransparent(B2D&,transparency)" ); 161cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 162cdf0e10cSrcweir 163cdf0e10cSrcweir // AW: Do NOT paint empty PolyPolygons 164cdf0e10cSrcweir if(!rB2DPolyPoly.count()) 165cdf0e10cSrcweir return; 166cdf0e10cSrcweir 167cdf0e10cSrcweir // we need a graphics 168cdf0e10cSrcweir if( !mpGraphics ) 169cdf0e10cSrcweir if( !ImplGetGraphics() ) 170cdf0e10cSrcweir return; 171cdf0e10cSrcweir 172cdf0e10cSrcweir if( mbInitClipRegion ) 173cdf0e10cSrcweir ImplInitClipRegion(); 174cdf0e10cSrcweir if( mbOutputClipped ) 175cdf0e10cSrcweir return; 176cdf0e10cSrcweir 177cdf0e10cSrcweir if( mbInitLineColor ) 178cdf0e10cSrcweir ImplInitLineColor(); 179cdf0e10cSrcweir if( mbInitFillColor ) 180cdf0e10cSrcweir ImplInitFillColor(); 181cdf0e10cSrcweir 182cdf0e10cSrcweir if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) 183cdf0e10cSrcweir && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) 184cdf0e10cSrcweir && ROP_OVERPAINT == GetRasterOp() ) 185cdf0e10cSrcweir { 186cdf0e10cSrcweir // b2dpolygon support not implemented yet on non-UNX platforms 187cdf0e10cSrcweir const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 188cdf0e10cSrcweir basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly); 189cdf0e10cSrcweir 190cdf0e10cSrcweir // transform the polygon into device space and ensure it is closed 191cdf0e10cSrcweir aB2DPolyPolygon.transform( aTransform ); 192cdf0e10cSrcweir aB2DPolyPolygon.setClosed( true ); 193cdf0e10cSrcweir 194cdf0e10cSrcweir bool bDrawnOk = true; 195cdf0e10cSrcweir if( IsFillColor() ) 196cdf0e10cSrcweir bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this ); 197cdf0e10cSrcweir if( bDrawnOk && IsLineColor() ) 198cdf0e10cSrcweir { 199cdf0e10cSrcweir const basegfx::B2DVector aHairlineWidth(1,1); 200cdf0e10cSrcweir const int nPolyCount = aB2DPolyPolygon.count(); 201cdf0e10cSrcweir for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) 202cdf0e10cSrcweir { 203cdf0e10cSrcweir const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx ); 204cdf0e10cSrcweir mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, this ); 205cdf0e10cSrcweir } 206cdf0e10cSrcweir } 207cdf0e10cSrcweir 208cdf0e10cSrcweir if( bDrawnOk ) 209cdf0e10cSrcweir { 210cdf0e10cSrcweir #if 0 211cdf0e10cSrcweir // MetaB2DPolyPolygonAction is not implemented yet: 212cdf0e10cSrcweir // according to AW adding it is very dangerous since there is a lot 213cdf0e10cSrcweir // of code that uses the metafile actions directly and unless every 214cdf0e10cSrcweir // place that does this knows about the new action we need to fallback 215cdf0e10cSrcweir if( mpMetaFile ) 216cdf0e10cSrcweir mpMetaFile->AddAction( new MetaB2DPolyPolygonAction( rB2DPolyPoly ) ); 217cdf0e10cSrcweir #else 218cdf0e10cSrcweir if( mpMetaFile ) 219cdf0e10cSrcweir mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0))); 220cdf0e10cSrcweir #endif 221cdf0e10cSrcweir return; 222cdf0e10cSrcweir } 223cdf0e10cSrcweir } 224cdf0e10cSrcweir 225cdf0e10cSrcweir // fallback to old polygon drawing if needed 226cdf0e10cSrcweir const PolyPolygon aToolsPolyPolygon( rB2DPolyPoly ); 227cdf0e10cSrcweir DrawTransparent(PolyPolygon(rB2DPolyPoly), static_cast< sal_uInt16 >(fTransparency * 100.0)); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir 230cdf0e10cSrcweir // ------------------------------------------------------------------------ 231cdf0e10cSrcweir 232cdf0e10cSrcweir void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly, 233cdf0e10cSrcweir sal_uInt16 nTransparencePercent ) 234cdf0e10cSrcweir { 235cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawTransparent()" ); 236cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 237cdf0e10cSrcweir 238cdf0e10cSrcweir // short circuit for drawing an opaque polygon 239cdf0e10cSrcweir if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) ) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir DrawPolyPolygon( rPolyPoly ); 242cdf0e10cSrcweir return; 243cdf0e10cSrcweir } 244cdf0e10cSrcweir 245cdf0e10cSrcweir // short circut for drawing an invisible polygon 246cdf0e10cSrcweir if( !mbFillColor || (nTransparencePercent >= 100) ) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir // short circuit if the polygon border is invisible too 249cdf0e10cSrcweir if( !mbLineColor ) 250cdf0e10cSrcweir return; 251cdf0e10cSrcweir 252cdf0e10cSrcweir // DrawTransparent() assumes that the border is NOT to be drawn transparently??? 253cdf0e10cSrcweir Push( PUSH_FILLCOLOR ); 254cdf0e10cSrcweir SetFillColor(); 255cdf0e10cSrcweir DrawPolyPolygon( rPolyPoly ); 256cdf0e10cSrcweir Pop(); 257cdf0e10cSrcweir return; 258cdf0e10cSrcweir } 259cdf0e10cSrcweir 260cdf0e10cSrcweir // handle metafile recording 261cdf0e10cSrcweir if( mpMetaFile ) 262cdf0e10cSrcweir mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) ); 263cdf0e10cSrcweir 264cdf0e10cSrcweir bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout(); 265cdf0e10cSrcweir if( bDrawn ) 266cdf0e10cSrcweir return; 267cdf0e10cSrcweir 268cdf0e10cSrcweir // get the device graphics as drawing target 269cdf0e10cSrcweir if( !mpGraphics ) 270cdf0e10cSrcweir if( !ImplGetGraphics() ) 271cdf0e10cSrcweir return; 272cdf0e10cSrcweir 273cdf0e10cSrcweir // debug helper: 274cdf0e10cSrcweir static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA"); 275cdf0e10cSrcweir 276cdf0e10cSrcweir // try hard to draw it directly, because the emulation layers are slower 277cdf0e10cSrcweir if( !pDisableNative 278cdf0e10cSrcweir && mpGraphics->supportsOperation( OutDevSupport_B2DDraw ) 279cdf0e10cSrcweir #if defined UNX && ! defined QUARTZ 280cdf0e10cSrcweir && GetBitCount() > 8 281cdf0e10cSrcweir #endif 282cdf0e10cSrcweir #ifdef WIN32 283cdf0e10cSrcweir // workaround bad dithering on remote displaying when using GDI+ with toolbar buttoin hilighting 284cdf0e10cSrcweir && !rPolyPoly.IsRect() 285cdf0e10cSrcweir #endif 286cdf0e10cSrcweir ) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir // prepare the graphics device 289cdf0e10cSrcweir if( mbInitClipRegion ) 290cdf0e10cSrcweir ImplInitClipRegion(); 291cdf0e10cSrcweir if( mbOutputClipped ) 292cdf0e10cSrcweir return; 293cdf0e10cSrcweir if( mbInitLineColor ) 294cdf0e10cSrcweir ImplInitLineColor(); 295cdf0e10cSrcweir if( mbInitFillColor ) 296cdf0e10cSrcweir ImplInitFillColor(); 297cdf0e10cSrcweir 298cdf0e10cSrcweir // get the polygon in device coordinates 299cdf0e10cSrcweir basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() ); 300cdf0e10cSrcweir const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); 301cdf0e10cSrcweir aB2DPolyPolygon.transform( aTransform ); 302cdf0e10cSrcweir 303cdf0e10cSrcweir const double fTransparency = 0.01 * nTransparencePercent; 304cdf0e10cSrcweir if( mbFillColor ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir // draw the transparent polygon 307cdf0e10cSrcweir // NOTE: filled polygons are assumed to be drawn as if they were always closed 308cdf0e10cSrcweir bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this ); 309cdf0e10cSrcweir } 310cdf0e10cSrcweir 311cdf0e10cSrcweir if( mbLineColor ) 312cdf0e10cSrcweir { 313cdf0e10cSrcweir // disable the fill color for now 314cdf0e10cSrcweir mpGraphics->SetFillColor(); 315cdf0e10cSrcweir // draw the border line 316cdf0e10cSrcweir const basegfx::B2DVector aLineWidths( 1, 1 ); 317cdf0e10cSrcweir const int nPolyCount = aB2DPolyPolygon.count(); 318cdf0e10cSrcweir for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) 319cdf0e10cSrcweir { 320cdf0e10cSrcweir const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx ); 321cdf0e10cSrcweir bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, this ); 322cdf0e10cSrcweir } 323cdf0e10cSrcweir // prepare to restore the fill color 324cdf0e10cSrcweir mbInitFillColor = mbFillColor; 325cdf0e10cSrcweir } 326cdf0e10cSrcweir } 327cdf0e10cSrcweir 328cdf0e10cSrcweir if( bDrawn ) 329cdf0e10cSrcweir return; 330cdf0e10cSrcweir 331cdf0e10cSrcweir if( 1 ) 332cdf0e10cSrcweir { 333cdf0e10cSrcweir VirtualDevice* pOldAlphaVDev = mpAlphaVDev; 334cdf0e10cSrcweir 335cdf0e10cSrcweir // #110958# Disable alpha VDev, we perform the necessary 336cdf0e10cSrcweir // operation explicitely further below. 337cdf0e10cSrcweir if( mpAlphaVDev ) 338cdf0e10cSrcweir mpAlphaVDev = NULL; 339cdf0e10cSrcweir 340cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 341cdf0e10cSrcweir mpMetaFile = NULL; 342cdf0e10cSrcweir 343cdf0e10cSrcweir if( OUTDEV_PRINTER == meOutDevType ) 344cdf0e10cSrcweir { 345cdf0e10cSrcweir if(100 <= nTransparencePercent) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir // #i112959# 100% transparent, draw nothing 348cdf0e10cSrcweir return; 349cdf0e10cSrcweir } 350cdf0e10cSrcweir 351cdf0e10cSrcweir Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() ); 352cdf0e10cSrcweir const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) ); 353cdf0e10cSrcweir const long nBaseExtent = Max( FRound( aDPISize.Width() / 300. ), 1L ); 354cdf0e10cSrcweir long nMove; 355cdf0e10cSrcweir const sal_uInt16 nTrans = ( nTransparencePercent < 13 ) ? 0 : 356cdf0e10cSrcweir ( nTransparencePercent < 38 ) ? 25 : 357cdf0e10cSrcweir ( nTransparencePercent < 63 ) ? 50 : 358cdf0e10cSrcweir ( nTransparencePercent < 88 ) ? 75 : 100; 359cdf0e10cSrcweir 360cdf0e10cSrcweir switch( nTrans ) 361cdf0e10cSrcweir { 362cdf0e10cSrcweir case( 25 ): nMove = nBaseExtent * 3; break; 363cdf0e10cSrcweir case( 50 ): nMove = nBaseExtent * 4; break; 364cdf0e10cSrcweir case( 75 ): nMove = nBaseExtent * 6; break; 365cdf0e10cSrcweir 366cdf0e10cSrcweir // #i112959# very transparent (88 < nTransparencePercent <= 99) 367cdf0e10cSrcweir case( 100 ): nMove = nBaseExtent * 8; break; 368cdf0e10cSrcweir 369cdf0e10cSrcweir // #i112959# not transparent (nTransparencePercent < 13) 370cdf0e10cSrcweir default: nMove = 0; break; 371cdf0e10cSrcweir } 372cdf0e10cSrcweir 373cdf0e10cSrcweir Push( PUSH_CLIPREGION | PUSH_LINECOLOR ); 374cdf0e10cSrcweir IntersectClipRegion( rPolyPoly ); 375cdf0e10cSrcweir SetLineColor( GetFillColor() ); 376cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 377cdf0e10cSrcweir EnableMapMode( sal_False ); 378cdf0e10cSrcweir 379cdf0e10cSrcweir if(nMove) 380cdf0e10cSrcweir { 381cdf0e10cSrcweir Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) ); 382cdf0e10cSrcweir while( aRect.Top() <= aPolyRect.Bottom() ) 383cdf0e10cSrcweir { 384cdf0e10cSrcweir DrawRect( aRect ); 385cdf0e10cSrcweir aRect.Move( 0, nMove ); 386cdf0e10cSrcweir } 387cdf0e10cSrcweir 388cdf0e10cSrcweir aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) ); 389cdf0e10cSrcweir while( aRect.Left() <= aPolyRect.Right() ) 390cdf0e10cSrcweir { 391cdf0e10cSrcweir DrawRect( aRect ); 392cdf0e10cSrcweir aRect.Move( nMove, 0 ); 393cdf0e10cSrcweir } 394cdf0e10cSrcweir } 395cdf0e10cSrcweir else 396cdf0e10cSrcweir { 397cdf0e10cSrcweir // #i112959# if not transparent, draw full rectangle in clip region 398cdf0e10cSrcweir DrawRect( aPolyRect ); 399cdf0e10cSrcweir } 400cdf0e10cSrcweir 401cdf0e10cSrcweir EnableMapMode( bOldMap ); 402cdf0e10cSrcweir Pop(); 403cdf0e10cSrcweir } 404cdf0e10cSrcweir else 405cdf0e10cSrcweir { 406cdf0e10cSrcweir PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) ); 407cdf0e10cSrcweir Rectangle aPolyRect( aPolyPoly.GetBoundRect() ); 408cdf0e10cSrcweir Point aPoint; 409cdf0e10cSrcweir Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 410cdf0e10cSrcweir 411cdf0e10cSrcweir aDstRect.Intersection( aPolyRect ); 412cdf0e10cSrcweir 413cdf0e10cSrcweir if( OUTDEV_WINDOW == meOutDevType ) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 416cdf0e10cSrcweir 417cdf0e10cSrcweir if( !aPaintRgn.IsNull() ) 418cdf0e10cSrcweir aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() ); 419cdf0e10cSrcweir } 420cdf0e10cSrcweir 421cdf0e10cSrcweir if( !aDstRect.IsEmpty() ) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir // #i66849# Added fast path for exactly rectangular 424cdf0e10cSrcweir // polygons 425cdf0e10cSrcweir // #i83087# Naturally, system alpha blending cannot 426cdf0e10cSrcweir // work with separate alpha VDev 427cdf0e10cSrcweir if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() ) 428cdf0e10cSrcweir { 429cdf0e10cSrcweir // setup Graphics only here (other cases delegate 430cdf0e10cSrcweir // to basic OutDev methods) 431cdf0e10cSrcweir if( 1 ) 432cdf0e10cSrcweir { 433cdf0e10cSrcweir if ( mbInitClipRegion ) 434cdf0e10cSrcweir ImplInitClipRegion(); 435cdf0e10cSrcweir if ( mbInitLineColor ) 436cdf0e10cSrcweir ImplInitLineColor(); 437cdf0e10cSrcweir if ( mbInitFillColor ) 438cdf0e10cSrcweir ImplInitFillColor(); 439cdf0e10cSrcweir 440cdf0e10cSrcweir Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() ); 441cdf0e10cSrcweir Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) ); 442cdf0e10cSrcweir 443cdf0e10cSrcweir if( !mbOutputClipped ) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir bDrawn = mpGraphics->DrawAlphaRect( 446cdf0e10cSrcweir aPixelRect.Left(), aPixelRect.Top(), 447cdf0e10cSrcweir // #i98405# use methods with small g, else one pixel too much will be painted. 448cdf0e10cSrcweir // This is because the source is a polygon which when painted would not paint 449cdf0e10cSrcweir // the rightmost and lowest pixel line(s), so use one pixel less for the 450cdf0e10cSrcweir // rectangle, too. 451cdf0e10cSrcweir aPixelRect.getWidth(), aPixelRect.getHeight(), 452cdf0e10cSrcweir sal::static_int_cast<sal_uInt8>(nTransparencePercent), 453cdf0e10cSrcweir this ); 454cdf0e10cSrcweir } 455cdf0e10cSrcweir else 456cdf0e10cSrcweir bDrawn = true; 457cdf0e10cSrcweir } 458cdf0e10cSrcweir } 459cdf0e10cSrcweir 460cdf0e10cSrcweir if( !bDrawn ) 461cdf0e10cSrcweir { 462cdf0e10cSrcweir VirtualDevice aVDev( *this, 1 ); 463cdf0e10cSrcweir const Size aDstSz( aDstRect.GetSize() ); 464cdf0e10cSrcweir const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 ); 465cdf0e10cSrcweir 466cdf0e10cSrcweir if( aDstRect.Left() || aDstRect.Top() ) 467cdf0e10cSrcweir aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() ); 468cdf0e10cSrcweir 469cdf0e10cSrcweir if( aVDev.SetOutputSizePixel( aDstSz ) ) 470cdf0e10cSrcweir { 471cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 472cdf0e10cSrcweir 473cdf0e10cSrcweir EnableMapMode( sal_False ); 474cdf0e10cSrcweir 475cdf0e10cSrcweir aVDev.SetLineColor( COL_BLACK ); 476cdf0e10cSrcweir aVDev.SetFillColor( COL_BLACK ); 477cdf0e10cSrcweir aVDev.DrawPolyPolygon( aPolyPoly ); 478cdf0e10cSrcweir 479cdf0e10cSrcweir Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) ); 480cdf0e10cSrcweir Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) ); 481cdf0e10cSrcweir 482cdf0e10cSrcweir // #107766# check for non-empty bitmaps before accessing them 483cdf0e10cSrcweir if( !!aPaint && !!aPolyMask ) 484cdf0e10cSrcweir { 485cdf0e10cSrcweir BitmapWriteAccess* pW = aPaint.AcquireWriteAccess(); 486cdf0e10cSrcweir BitmapReadAccess* pR = aPolyMask.AcquireReadAccess(); 487cdf0e10cSrcweir 488cdf0e10cSrcweir if( pW && pR ) 489cdf0e10cSrcweir { 490cdf0e10cSrcweir BitmapColor aPixCol; 491cdf0e10cSrcweir const BitmapColor aFillCol( GetFillColor() ); 492cdf0e10cSrcweir const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) ); 493cdf0e10cSrcweir const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) ); 494cdf0e10cSrcweir const long nWidth = pW->Width(), nHeight = pW->Height(); 495cdf0e10cSrcweir const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue(); 496cdf0e10cSrcweir long nX, nY; 497cdf0e10cSrcweir 498cdf0e10cSrcweir if( aPaint.GetBitCount() <= 8 ) 499cdf0e10cSrcweir { 500cdf0e10cSrcweir const BitmapPalette& rPal = pW->GetPalette(); 501cdf0e10cSrcweir const sal_uInt16 nCount = rPal.GetEntryCount(); 502cdf0e10cSrcweir BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ]; 503cdf0e10cSrcweir 504cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nCount; i++ ) 505cdf0e10cSrcweir { 506cdf0e10cSrcweir BitmapColor aCol( rPal[ i ] ); 507cdf0e10cSrcweir pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) ); 508cdf0e10cSrcweir } 509cdf0e10cSrcweir 510cdf0e10cSrcweir if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 511cdf0e10cSrcweir pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ) 512cdf0e10cSrcweir { 513cdf0e10cSrcweir const sal_uInt8 cBlack = aBlack.GetIndex(); 514cdf0e10cSrcweir 515cdf0e10cSrcweir for( nY = 0; nY < nHeight; nY++ ) 516cdf0e10cSrcweir { 517cdf0e10cSrcweir Scanline pWScan = pW->GetScanline( nY ); 518cdf0e10cSrcweir Scanline pRScan = pR->GetScanline( nY ); 519cdf0e10cSrcweir sal_uInt8 cBit = 128; 520cdf0e10cSrcweir 521cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ ) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir if( !cBit ) 524cdf0e10cSrcweir cBit = 128, pRScan++; 525cdf0e10cSrcweir 526cdf0e10cSrcweir if( ( *pRScan & cBit ) == cBlack ) 527cdf0e10cSrcweir *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex(); 528cdf0e10cSrcweir } 529cdf0e10cSrcweir } 530cdf0e10cSrcweir } 531cdf0e10cSrcweir else 532cdf0e10cSrcweir { 533cdf0e10cSrcweir for( nY = 0; nY < nHeight; nY++ ) 534cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) 535cdf0e10cSrcweir if( pR->GetPixel( nY, nX ) == aBlack ) 536cdf0e10cSrcweir pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] ); 537cdf0e10cSrcweir } 538cdf0e10cSrcweir 539cdf0e10cSrcweir delete[] (sal_uInt8*) pMap; 540cdf0e10cSrcweir } 541cdf0e10cSrcweir else 542cdf0e10cSrcweir { 543cdf0e10cSrcweir if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL && 544cdf0e10cSrcweir pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR ) 545cdf0e10cSrcweir { 546cdf0e10cSrcweir const sal_uInt8 cBlack = aBlack.GetIndex(); 547cdf0e10cSrcweir 548cdf0e10cSrcweir for( nY = 0; nY < nHeight; nY++ ) 549cdf0e10cSrcweir { 550cdf0e10cSrcweir Scanline pWScan = pW->GetScanline( nY ); 551cdf0e10cSrcweir Scanline pRScan = pR->GetScanline( nY ); 552cdf0e10cSrcweir sal_uInt8 cBit = 128; 553cdf0e10cSrcweir 554cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 ) 555cdf0e10cSrcweir { 556cdf0e10cSrcweir if( !cBit ) 557cdf0e10cSrcweir cBit = 128, pRScan++; 558cdf0e10cSrcweir 559cdf0e10cSrcweir if( ( *pRScan & cBit ) == cBlack ) 560cdf0e10cSrcweir { 561cdf0e10cSrcweir pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans ); 562cdf0e10cSrcweir pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans ); 563cdf0e10cSrcweir pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans ); 564cdf0e10cSrcweir } 565cdf0e10cSrcweir } 566cdf0e10cSrcweir } 567cdf0e10cSrcweir } 568cdf0e10cSrcweir else 569cdf0e10cSrcweir { 570cdf0e10cSrcweir for( nY = 0; nY < nHeight; nY++ ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir for( nX = 0; nX < nWidth; nX++ ) 573cdf0e10cSrcweir { 574cdf0e10cSrcweir if( pR->GetPixel( nY, nX ) == aBlack ) 575cdf0e10cSrcweir { 576cdf0e10cSrcweir aPixCol = pW->GetColor( nY, nX ); 577cdf0e10cSrcweir pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) ); 578cdf0e10cSrcweir } 579cdf0e10cSrcweir } 580cdf0e10cSrcweir } 581cdf0e10cSrcweir } 582cdf0e10cSrcweir } 583cdf0e10cSrcweir } 584cdf0e10cSrcweir 585cdf0e10cSrcweir aPolyMask.ReleaseAccess( pR ); 586cdf0e10cSrcweir aPaint.ReleaseAccess( pW ); 587cdf0e10cSrcweir 588cdf0e10cSrcweir DrawBitmap( aDstRect.TopLeft(), aPaint ); 589cdf0e10cSrcweir 590cdf0e10cSrcweir EnableMapMode( bOldMap ); 591cdf0e10cSrcweir 592cdf0e10cSrcweir if( mbLineColor ) 593cdf0e10cSrcweir { 594cdf0e10cSrcweir Push( PUSH_FILLCOLOR ); 595cdf0e10cSrcweir SetFillColor(); 596cdf0e10cSrcweir DrawPolyPolygon( rPolyPoly ); 597cdf0e10cSrcweir Pop(); 598cdf0e10cSrcweir } 599cdf0e10cSrcweir } 600cdf0e10cSrcweir } 601cdf0e10cSrcweir else 602cdf0e10cSrcweir DrawPolyPolygon( rPolyPoly ); 603cdf0e10cSrcweir } 604cdf0e10cSrcweir } 605cdf0e10cSrcweir } 606cdf0e10cSrcweir 607cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 608cdf0e10cSrcweir 609cdf0e10cSrcweir // #110958# Restore disabled alpha VDev 610cdf0e10cSrcweir mpAlphaVDev = pOldAlphaVDev; 611cdf0e10cSrcweir 612cdf0e10cSrcweir // #110958# Apply alpha value also to VDev alpha channel 613cdf0e10cSrcweir if( mpAlphaVDev ) 614cdf0e10cSrcweir { 615cdf0e10cSrcweir const Color aFillCol( mpAlphaVDev->GetFillColor() ); 616cdf0e10cSrcweir mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100), 617cdf0e10cSrcweir sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100), 618cdf0e10cSrcweir sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) ); 619cdf0e10cSrcweir 620cdf0e10cSrcweir mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent ); 621cdf0e10cSrcweir 622cdf0e10cSrcweir mpAlphaVDev->SetFillColor( aFillCol ); 623cdf0e10cSrcweir } 624cdf0e10cSrcweir } 625cdf0e10cSrcweir } 626cdf0e10cSrcweir 627cdf0e10cSrcweir // ----------------------------------------------------------------------- 628cdf0e10cSrcweir 629cdf0e10cSrcweir void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, 630cdf0e10cSrcweir const Size& rSize, const Gradient& rTransparenceGradient ) 631cdf0e10cSrcweir { 632cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawTransparent()" ); 633cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 634cdf0e10cSrcweir 635cdf0e10cSrcweir const Color aBlack( COL_BLACK ); 636cdf0e10cSrcweir 637cdf0e10cSrcweir if( mpMetaFile ) 638cdf0e10cSrcweir mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) ); 639cdf0e10cSrcweir 640cdf0e10cSrcweir if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) || 641cdf0e10cSrcweir ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) ) 642cdf0e10cSrcweir { 643cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 644cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize ); 645cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 646cdf0e10cSrcweir } 647cdf0e10cSrcweir else 648cdf0e10cSrcweir { 649cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 650cdf0e10cSrcweir Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) ); 651cdf0e10cSrcweir Point aPoint; 652cdf0e10cSrcweir Rectangle aDstRect( aPoint, GetOutputSizePixel() ); 653cdf0e10cSrcweir 654cdf0e10cSrcweir mpMetaFile = NULL; 655cdf0e10cSrcweir aDstRect.Intersection( aOutRect ); 656cdf0e10cSrcweir 657cdf0e10cSrcweir if( OUTDEV_WINDOW == meOutDevType ) 658cdf0e10cSrcweir { 659cdf0e10cSrcweir const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 660cdf0e10cSrcweir 661cdf0e10cSrcweir if( !aPaintRgn.IsNull() ) 662cdf0e10cSrcweir aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) ); 663cdf0e10cSrcweir } 664cdf0e10cSrcweir 665cdf0e10cSrcweir if( !aDstRect.IsEmpty() ) 666cdf0e10cSrcweir { 667cdf0e10cSrcweir VirtualDevice* pVDev = new VirtualDevice; 668cdf0e10cSrcweir 669cdf0e10cSrcweir ((OutputDevice*)pVDev)->mnDPIX = mnDPIX; 670cdf0e10cSrcweir ((OutputDevice*)pVDev)->mnDPIY = mnDPIY; 671cdf0e10cSrcweir 672cdf0e10cSrcweir if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) ) 673cdf0e10cSrcweir { 674cdf0e10cSrcweir if(GetAntialiasing()) 675cdf0e10cSrcweir { 676cdf0e10cSrcweir // #i102109# 677cdf0e10cSrcweir // For MetaFile replay (see task) it may now be neccessary to take 678cdf0e10cSrcweir // into account that the content is AntiAlialised and needs to be masked 679cdf0e10cSrcweir // like that. Instead of masking, i will use a copy-modify-paste cycle 680cdf0e10cSrcweir // here (as i already use in the VclPrimiziveRenderer with successs) 681cdf0e10cSrcweir pVDev->SetAntialiasing(GetAntialiasing()); 682cdf0e10cSrcweir 683cdf0e10cSrcweir // create MapMode for buffer (offset needed) and set 684cdf0e10cSrcweir MapMode aMap(GetMapMode()); 685cdf0e10cSrcweir const Point aOutPos(PixelToLogic(aDstRect.TopLeft())); 686cdf0e10cSrcweir aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y())); 687cdf0e10cSrcweir pVDev->SetMapMode(aMap); 688cdf0e10cSrcweir 689cdf0e10cSrcweir // copy MapMode state and disable for target 690cdf0e10cSrcweir const bool bOrigMapModeEnabled(IsMapModeEnabled()); 691cdf0e10cSrcweir EnableMapMode(false); 692cdf0e10cSrcweir 693cdf0e10cSrcweir // copy MapMode state and disable for buffer 694cdf0e10cSrcweir const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled()); 695cdf0e10cSrcweir pVDev->EnableMapMode(false); 696cdf0e10cSrcweir 697cdf0e10cSrcweir // copy content from original to buffer 698cdf0e10cSrcweir pVDev->DrawOutDev( 699cdf0e10cSrcweir aPoint, pVDev->GetOutputSizePixel(), // dest 700cdf0e10cSrcweir aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source 701cdf0e10cSrcweir *this); 702cdf0e10cSrcweir 703cdf0e10cSrcweir // draw MetaFile to buffer 704cdf0e10cSrcweir pVDev->EnableMapMode(bBufferMapModeEnabled); 705cdf0e10cSrcweir ((GDIMetaFile&)rMtf).WindStart(); 706cdf0e10cSrcweir ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize); 707cdf0e10cSrcweir ((GDIMetaFile&)rMtf).WindStart(); 708cdf0e10cSrcweir 709cdf0e10cSrcweir // get content bitmap from buffer 710cdf0e10cSrcweir pVDev->EnableMapMode(false); 711cdf0e10cSrcweir const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 712cdf0e10cSrcweir 713cdf0e10cSrcweir // create alpha mask from gradient and get as Bitmap 714cdf0e10cSrcweir pVDev->EnableMapMode(bBufferMapModeEnabled); 715cdf0e10cSrcweir pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT); 716cdf0e10cSrcweir pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient); 717cdf0e10cSrcweir pVDev->SetDrawMode(DRAWMODE_DEFAULT); 718cdf0e10cSrcweir pVDev->EnableMapMode(false); 719cdf0e10cSrcweir const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel())); 720cdf0e10cSrcweir 721cdf0e10cSrcweir // draw masked content to target and restore MapMode 722cdf0e10cSrcweir DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha)); 723cdf0e10cSrcweir EnableMapMode(bOrigMapModeEnabled); 724cdf0e10cSrcweir } 725cdf0e10cSrcweir else 726cdf0e10cSrcweir { 727cdf0e10cSrcweir Bitmap aPaint, aMask; 728cdf0e10cSrcweir AlphaMask aAlpha; 729cdf0e10cSrcweir MapMode aMap( GetMapMode() ); 730cdf0e10cSrcweir Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) ); 731cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 732cdf0e10cSrcweir 733cdf0e10cSrcweir aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) ); 734cdf0e10cSrcweir pVDev->SetMapMode( aMap ); 735cdf0e10cSrcweir const sal_Bool bVDevOldMap = pVDev->IsMapModeEnabled(); 736cdf0e10cSrcweir 737cdf0e10cSrcweir // create paint bitmap 738cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 739cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 740cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 741cdf0e10cSrcweir pVDev->EnableMapMode( sal_False ); 742cdf0e10cSrcweir aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 743cdf0e10cSrcweir pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 744cdf0e10cSrcweir 745cdf0e10cSrcweir // create mask bitmap 746cdf0e10cSrcweir pVDev->SetLineColor( COL_BLACK ); 747cdf0e10cSrcweir pVDev->SetFillColor( COL_BLACK ); 748cdf0e10cSrcweir pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) ); 749cdf0e10cSrcweir pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT | 750cdf0e10cSrcweir DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT ); 751cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 752cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize ); 753cdf0e10cSrcweir ( (GDIMetaFile&) rMtf ).WindStart(); 754cdf0e10cSrcweir pVDev->EnableMapMode( sal_False ); 755cdf0e10cSrcweir aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 756cdf0e10cSrcweir pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here! 757cdf0e10cSrcweir 758cdf0e10cSrcweir // create alpha mask from gradient 759cdf0e10cSrcweir pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT ); 760cdf0e10cSrcweir pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient ); 761cdf0e10cSrcweir pVDev->SetDrawMode( DRAWMODE_DEFAULT ); 762cdf0e10cSrcweir pVDev->EnableMapMode( sal_False ); 763cdf0e10cSrcweir pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) ); 764cdf0e10cSrcweir 765cdf0e10cSrcweir aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() ); 766cdf0e10cSrcweir 767cdf0e10cSrcweir delete pVDev; 768cdf0e10cSrcweir 769cdf0e10cSrcweir EnableMapMode( sal_False ); 770cdf0e10cSrcweir DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) ); 771cdf0e10cSrcweir EnableMapMode( bOldMap ); 772cdf0e10cSrcweir } 773cdf0e10cSrcweir } 774cdf0e10cSrcweir else 775cdf0e10cSrcweir delete pVDev; 776cdf0e10cSrcweir } 777cdf0e10cSrcweir 778cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 779cdf0e10cSrcweir } 780cdf0e10cSrcweir } 781cdf0e10cSrcweir 782cdf0e10cSrcweir // ----------------------------------------------------------------------- 783cdf0e10cSrcweir 784cdf0e10cSrcweir void OutputDevice::ImplDrawColorWallpaper( long nX, long nY, 785cdf0e10cSrcweir long nWidth, long nHeight, 786cdf0e10cSrcweir const Wallpaper& rWallpaper ) 787cdf0e10cSrcweir { 788cdf0e10cSrcweir // Wallpaper ohne Umrandung zeichnen 789cdf0e10cSrcweir Color aOldLineColor = GetLineColor(); 790cdf0e10cSrcweir Color aOldFillColor = GetFillColor(); 791cdf0e10cSrcweir SetLineColor(); 792cdf0e10cSrcweir SetFillColor( rWallpaper.GetColor() ); 793cdf0e10cSrcweir sal_Bool bMap = mbMap; 794cdf0e10cSrcweir EnableMapMode( sal_False ); 795cdf0e10cSrcweir DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 796cdf0e10cSrcweir SetLineColor( aOldLineColor ); 797cdf0e10cSrcweir SetFillColor( aOldFillColor ); 798cdf0e10cSrcweir EnableMapMode( bMap ); 799cdf0e10cSrcweir } 800cdf0e10cSrcweir 801cdf0e10cSrcweir // ----------------------------------------------------------------------- 802cdf0e10cSrcweir 803cdf0e10cSrcweir void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY, 804cdf0e10cSrcweir long nWidth, long nHeight, 805cdf0e10cSrcweir const Wallpaper& rWallpaper ) 806cdf0e10cSrcweir { 807cdf0e10cSrcweir BitmapEx aBmpEx; 808cdf0e10cSrcweir const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap(); 809cdf0e10cSrcweir Point aPos; 810cdf0e10cSrcweir Size aSize; 811cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 812cdf0e10cSrcweir const WallpaperStyle eStyle = rWallpaper.GetStyle(); 813cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 814cdf0e10cSrcweir sal_Bool bDrawn = sal_False; 815cdf0e10cSrcweir sal_Bool bDrawGradientBackground = sal_False; 816cdf0e10cSrcweir sal_Bool bDrawColorBackground = sal_False; 817cdf0e10cSrcweir 818cdf0e10cSrcweir if( pCached ) 819cdf0e10cSrcweir aBmpEx = *pCached; 820cdf0e10cSrcweir else 821cdf0e10cSrcweir aBmpEx = rWallpaper.GetBitmap(); 822cdf0e10cSrcweir 823cdf0e10cSrcweir const long nBmpWidth = aBmpEx.GetSizePixel().Width(); 824cdf0e10cSrcweir const long nBmpHeight = aBmpEx.GetSizePixel().Height(); 825cdf0e10cSrcweir const sal_Bool bTransparent = aBmpEx.IsTransparent(); 826cdf0e10cSrcweir 827cdf0e10cSrcweir // draw background 828cdf0e10cSrcweir if( bTransparent ) 829cdf0e10cSrcweir { 830cdf0e10cSrcweir if( rWallpaper.IsGradient() ) 831cdf0e10cSrcweir bDrawGradientBackground = sal_True; 832cdf0e10cSrcweir else 833cdf0e10cSrcweir { 834cdf0e10cSrcweir if( !pCached && !rWallpaper.GetColor().GetTransparency() ) 835cdf0e10cSrcweir { 836cdf0e10cSrcweir VirtualDevice aVDev( *this ); 837cdf0e10cSrcweir aVDev.SetBackground( rWallpaper.GetColor() ); 838cdf0e10cSrcweir aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) ); 839cdf0e10cSrcweir aVDev.DrawBitmapEx( Point(), aBmpEx ); 840cdf0e10cSrcweir aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 841cdf0e10cSrcweir } 842cdf0e10cSrcweir 843cdf0e10cSrcweir bDrawColorBackground = sal_True; 844cdf0e10cSrcweir } 845cdf0e10cSrcweir } 846cdf0e10cSrcweir else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE ) 847cdf0e10cSrcweir { 848cdf0e10cSrcweir if( rWallpaper.IsGradient() ) 849cdf0e10cSrcweir bDrawGradientBackground = sal_True; 850cdf0e10cSrcweir else 851cdf0e10cSrcweir bDrawColorBackground = sal_True; 852cdf0e10cSrcweir } 853cdf0e10cSrcweir 854cdf0e10cSrcweir // background of bitmap? 855cdf0e10cSrcweir if( bDrawGradientBackground ) 856cdf0e10cSrcweir ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 857cdf0e10cSrcweir else if( bDrawColorBackground && bTransparent ) 858cdf0e10cSrcweir { 859cdf0e10cSrcweir ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 860cdf0e10cSrcweir bDrawColorBackground = sal_False; 861cdf0e10cSrcweir } 862cdf0e10cSrcweir 863cdf0e10cSrcweir // calc pos and size 864cdf0e10cSrcweir if( rWallpaper.IsRect() ) 865cdf0e10cSrcweir { 866cdf0e10cSrcweir const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) ); 867cdf0e10cSrcweir aPos = aBound.TopLeft(); 868cdf0e10cSrcweir aSize = aBound.GetSize(); 869cdf0e10cSrcweir } 870cdf0e10cSrcweir else 871cdf0e10cSrcweir { 872cdf0e10cSrcweir aPos = Point( nX, nY ); 873cdf0e10cSrcweir aSize = Size( nWidth, nHeight ); 874cdf0e10cSrcweir } 875cdf0e10cSrcweir 876cdf0e10cSrcweir mpMetaFile = NULL; 877cdf0e10cSrcweir EnableMapMode( sal_False ); 878cdf0e10cSrcweir Push( PUSH_CLIPREGION ); 879cdf0e10cSrcweir IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 880cdf0e10cSrcweir 881cdf0e10cSrcweir switch( eStyle ) 882cdf0e10cSrcweir { 883cdf0e10cSrcweir case( WALLPAPER_SCALE ): 884cdf0e10cSrcweir { 885cdf0e10cSrcweir if( !pCached || ( pCached->GetSizePixel() != aSize ) ) 886cdf0e10cSrcweir { 887cdf0e10cSrcweir if( pCached ) 888cdf0e10cSrcweir rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap(); 889cdf0e10cSrcweir 890cdf0e10cSrcweir aBmpEx = rWallpaper.GetBitmap(); 891cdf0e10cSrcweir aBmpEx.Scale( aSize ); 892cdf0e10cSrcweir aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() ); 893cdf0e10cSrcweir } 894cdf0e10cSrcweir } 895cdf0e10cSrcweir break; 896cdf0e10cSrcweir 897cdf0e10cSrcweir case( WALLPAPER_TOPLEFT ): 898cdf0e10cSrcweir break; 899cdf0e10cSrcweir 900cdf0e10cSrcweir case( WALLPAPER_TOP ): 901cdf0e10cSrcweir aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 902cdf0e10cSrcweir break; 903cdf0e10cSrcweir 904cdf0e10cSrcweir case( WALLPAPER_TOPRIGHT ): 905cdf0e10cSrcweir aPos.X() += ( aSize.Width() - nBmpWidth ); 906cdf0e10cSrcweir break; 907cdf0e10cSrcweir 908cdf0e10cSrcweir case( WALLPAPER_LEFT ): 909cdf0e10cSrcweir aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 910cdf0e10cSrcweir break; 911cdf0e10cSrcweir 912cdf0e10cSrcweir case( WALLPAPER_CENTER ): 913cdf0e10cSrcweir { 914cdf0e10cSrcweir aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 915cdf0e10cSrcweir aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 916cdf0e10cSrcweir } 917cdf0e10cSrcweir break; 918cdf0e10cSrcweir 919cdf0e10cSrcweir case( WALLPAPER_RIGHT ): 920cdf0e10cSrcweir { 921cdf0e10cSrcweir aPos.X() += ( aSize.Width() - nBmpWidth ); 922cdf0e10cSrcweir aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1; 923cdf0e10cSrcweir } 924cdf0e10cSrcweir break; 925cdf0e10cSrcweir 926cdf0e10cSrcweir case( WALLPAPER_BOTTOMLEFT ): 927cdf0e10cSrcweir aPos.Y() += ( aSize.Height() - nBmpHeight ); 928cdf0e10cSrcweir break; 929cdf0e10cSrcweir 930cdf0e10cSrcweir case( WALLPAPER_BOTTOM ): 931cdf0e10cSrcweir { 932cdf0e10cSrcweir aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1; 933cdf0e10cSrcweir aPos.Y() += ( aSize.Height() - nBmpHeight ); 934cdf0e10cSrcweir } 935cdf0e10cSrcweir break; 936cdf0e10cSrcweir 937cdf0e10cSrcweir case( WALLPAPER_BOTTOMRIGHT ): 938cdf0e10cSrcweir { 939cdf0e10cSrcweir aPos.X() += ( aSize.Width() - nBmpWidth ); 940cdf0e10cSrcweir aPos.Y() += ( aSize.Height() - nBmpHeight ); 941cdf0e10cSrcweir } 942cdf0e10cSrcweir break; 943cdf0e10cSrcweir 944cdf0e10cSrcweir default: 945cdf0e10cSrcweir { 946cdf0e10cSrcweir const long nRight = nX + nWidth - 1L; 947cdf0e10cSrcweir const long nBottom = nY + nHeight - 1L; 948cdf0e10cSrcweir long nFirstX; 949cdf0e10cSrcweir long nFirstY; 950cdf0e10cSrcweir 951cdf0e10cSrcweir if( eStyle == WALLPAPER_TILE ) 952cdf0e10cSrcweir { 953cdf0e10cSrcweir nFirstX = aPos.X(); 954cdf0e10cSrcweir nFirstY = aPos.Y(); 955cdf0e10cSrcweir } 956cdf0e10cSrcweir else 957cdf0e10cSrcweir { 958cdf0e10cSrcweir nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 ); 959cdf0e10cSrcweir nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 ); 960cdf0e10cSrcweir } 961cdf0e10cSrcweir 962cdf0e10cSrcweir const long nOffX = ( nFirstX - nX ) % nBmpWidth; 963cdf0e10cSrcweir const long nOffY = ( nFirstY - nY ) % nBmpHeight; 964cdf0e10cSrcweir long nStartX = nX + nOffX; 965cdf0e10cSrcweir long nStartY = nY + nOffY; 966cdf0e10cSrcweir 967cdf0e10cSrcweir if( nOffX > 0L ) 968cdf0e10cSrcweir nStartX -= nBmpWidth; 969cdf0e10cSrcweir 970cdf0e10cSrcweir if( nOffY > 0L ) 971cdf0e10cSrcweir nStartY -= nBmpHeight; 972cdf0e10cSrcweir 973cdf0e10cSrcweir for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight ) 974cdf0e10cSrcweir for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth ) 975cdf0e10cSrcweir DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx ); 976cdf0e10cSrcweir 977cdf0e10cSrcweir bDrawn = sal_True; 978cdf0e10cSrcweir } 979cdf0e10cSrcweir break; 980cdf0e10cSrcweir } 981cdf0e10cSrcweir 982cdf0e10cSrcweir if( !bDrawn ) 983cdf0e10cSrcweir { 984cdf0e10cSrcweir // optimized for non-transparent bitmaps 985cdf0e10cSrcweir if( bDrawColorBackground ) 986cdf0e10cSrcweir { 987cdf0e10cSrcweir const Size aBmpSize( aBmpEx.GetSizePixel() ); 988cdf0e10cSrcweir const Point aTmpPoint; 989cdf0e10cSrcweir const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() ); 990cdf0e10cSrcweir const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) ); 991cdf0e10cSrcweir Rectangle aWorkRect; 992cdf0e10cSrcweir 993cdf0e10cSrcweir aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L ); 994cdf0e10cSrcweir aWorkRect.Justify(); 995cdf0e10cSrcweir aWorkRect.Intersection( aColRect ); 996cdf0e10cSrcweir if( !aWorkRect.IsEmpty() ) 997cdf0e10cSrcweir { 998cdf0e10cSrcweir ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 999cdf0e10cSrcweir aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1000cdf0e10cSrcweir rWallpaper ); 1001cdf0e10cSrcweir } 1002cdf0e10cSrcweir 1003cdf0e10cSrcweir aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L ); 1004cdf0e10cSrcweir aWorkRect.Justify(); 1005cdf0e10cSrcweir aWorkRect.Intersection( aColRect ); 1006cdf0e10cSrcweir if( !aWorkRect.IsEmpty() ) 1007cdf0e10cSrcweir { 1008cdf0e10cSrcweir ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1009cdf0e10cSrcweir aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1010cdf0e10cSrcweir rWallpaper ); 1011cdf0e10cSrcweir } 1012cdf0e10cSrcweir 1013cdf0e10cSrcweir aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L ); 1014cdf0e10cSrcweir aWorkRect.Justify(); 1015cdf0e10cSrcweir aWorkRect.Intersection( aColRect ); 1016cdf0e10cSrcweir if( !aWorkRect.IsEmpty() ) 1017cdf0e10cSrcweir { 1018cdf0e10cSrcweir ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1019cdf0e10cSrcweir aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1020cdf0e10cSrcweir rWallpaper ); 1021cdf0e10cSrcweir } 1022cdf0e10cSrcweir 1023cdf0e10cSrcweir aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() ); 1024cdf0e10cSrcweir aWorkRect.Justify(); 1025cdf0e10cSrcweir aWorkRect.Intersection( aColRect ); 1026cdf0e10cSrcweir if( !aWorkRect.IsEmpty() ) 1027cdf0e10cSrcweir { 1028cdf0e10cSrcweir ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(), 1029cdf0e10cSrcweir aWorkRect.GetWidth(), aWorkRect.GetHeight(), 1030cdf0e10cSrcweir rWallpaper ); 1031cdf0e10cSrcweir } 1032cdf0e10cSrcweir } 1033cdf0e10cSrcweir 1034cdf0e10cSrcweir DrawBitmapEx( aPos, aBmpEx ); 1035cdf0e10cSrcweir } 1036cdf0e10cSrcweir 1037cdf0e10cSrcweir rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx ); 1038cdf0e10cSrcweir 1039cdf0e10cSrcweir Pop(); 1040cdf0e10cSrcweir EnableMapMode( bOldMap ); 1041cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 1042cdf0e10cSrcweir } 1043cdf0e10cSrcweir 1044cdf0e10cSrcweir // ----------------------------------------------------------------------- 1045cdf0e10cSrcweir 1046cdf0e10cSrcweir void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY, 1047cdf0e10cSrcweir long nWidth, long nHeight, 1048cdf0e10cSrcweir const Wallpaper& rWallpaper ) 1049cdf0e10cSrcweir { 1050cdf0e10cSrcweir Rectangle aBound; 1051cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 1052cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 1053cdf0e10cSrcweir sal_Bool bNeedGradient = sal_True; 1054cdf0e10cSrcweir 1055cdf0e10cSrcweir /* 1056cdf0e10cSrcweir if ( rWallpaper.IsRect() ) 1057cdf0e10cSrcweir aBound = LogicToPixel( rWallpaper.GetRect() ); 1058cdf0e10cSrcweir else 1059cdf0e10cSrcweir */ 1060cdf0e10cSrcweir aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ); 1061cdf0e10cSrcweir 1062cdf0e10cSrcweir mpMetaFile = NULL; 1063cdf0e10cSrcweir EnableMapMode( sal_False ); 1064cdf0e10cSrcweir Push( PUSH_CLIPREGION ); 1065cdf0e10cSrcweir IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) ); 1066cdf0e10cSrcweir 1067cdf0e10cSrcweir if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT ) 1068cdf0e10cSrcweir { 1069cdf0e10cSrcweir Window *pWin = dynamic_cast< Window* >( this ); 1070cdf0e10cSrcweir if( pWin ) 1071cdf0e10cSrcweir { 1072cdf0e10cSrcweir // limit gradient to useful size, so that it still can be noticed 1073cdf0e10cSrcweir // in maximized windows 1074cdf0e10cSrcweir long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width(); 1075cdf0e10cSrcweir if( gradientWidth > 1024 ) 1076cdf0e10cSrcweir gradientWidth = 1024; 1077cdf0e10cSrcweir if( mnOutOffX+nWidth > gradientWidth ) 1078cdf0e10cSrcweir ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() ); 1079cdf0e10cSrcweir if( mnOutOffX > gradientWidth ) 1080cdf0e10cSrcweir bNeedGradient = sal_False; 1081cdf0e10cSrcweir else 1082cdf0e10cSrcweir aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) ); 1083cdf0e10cSrcweir } 1084cdf0e10cSrcweir } 1085cdf0e10cSrcweir 1086cdf0e10cSrcweir if( bNeedGradient ) 1087cdf0e10cSrcweir DrawGradient( aBound, rWallpaper.GetGradient() ); 1088cdf0e10cSrcweir 1089cdf0e10cSrcweir Pop(); 1090cdf0e10cSrcweir EnableMapMode( bOldMap ); 1091cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 1092cdf0e10cSrcweir } 1093cdf0e10cSrcweir 1094cdf0e10cSrcweir // ----------------------------------------------------------------------- 1095cdf0e10cSrcweir 1096cdf0e10cSrcweir void OutputDevice::ImplDrawWallpaper( long nX, long nY, 1097cdf0e10cSrcweir long nWidth, long nHeight, 1098cdf0e10cSrcweir const Wallpaper& rWallpaper ) 1099cdf0e10cSrcweir { 1100cdf0e10cSrcweir if( rWallpaper.IsBitmap() ) 1101cdf0e10cSrcweir ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1102cdf0e10cSrcweir else if( rWallpaper.IsGradient() ) 1103cdf0e10cSrcweir ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1104cdf0e10cSrcweir else 1105cdf0e10cSrcweir ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper ); 1106cdf0e10cSrcweir } 1107cdf0e10cSrcweir 1108cdf0e10cSrcweir // ----------------------------------------------------------------------- 1109cdf0e10cSrcweir 1110cdf0e10cSrcweir void OutputDevice::DrawWallpaper( const Rectangle& rRect, 1111cdf0e10cSrcweir const Wallpaper& rWallpaper ) 1112cdf0e10cSrcweir { 1113cdf0e10cSrcweir if ( mpMetaFile ) 1114cdf0e10cSrcweir mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) ); 1115cdf0e10cSrcweir 1116cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1117cdf0e10cSrcweir return; 1118cdf0e10cSrcweir 1119cdf0e10cSrcweir if ( rWallpaper.GetStyle() != WALLPAPER_NULL ) 1120cdf0e10cSrcweir { 1121cdf0e10cSrcweir Rectangle aRect = LogicToPixel( rRect ); 1122cdf0e10cSrcweir aRect.Justify(); 1123cdf0e10cSrcweir 1124cdf0e10cSrcweir if ( !aRect.IsEmpty() ) 1125cdf0e10cSrcweir { 1126cdf0e10cSrcweir ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1127cdf0e10cSrcweir rWallpaper ); 1128cdf0e10cSrcweir } 1129cdf0e10cSrcweir } 1130cdf0e10cSrcweir 1131cdf0e10cSrcweir if( mpAlphaVDev ) 1132cdf0e10cSrcweir mpAlphaVDev->DrawWallpaper( rRect, rWallpaper ); 1133cdf0e10cSrcweir } 1134cdf0e10cSrcweir 1135cdf0e10cSrcweir // ----------------------------------------------------------------------- 1136cdf0e10cSrcweir 1137cdf0e10cSrcweir void OutputDevice::Erase() 1138cdf0e10cSrcweir { 1139cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1140cdf0e10cSrcweir return; 1141cdf0e10cSrcweir 1142cdf0e10cSrcweir sal_Bool bNativeOK = sal_False; 1143cdf0e10cSrcweir 1144cdf0e10cSrcweir if( meOutDevType == OUTDEV_WINDOW ) 1145cdf0e10cSrcweir { 1146cdf0e10cSrcweir Window* pWindow = static_cast<Window*>(this); 1147cdf0e10cSrcweir ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground; 1148cdf0e10cSrcweir if( aCtrlPart != 0 && ! pWindow->IsControlBackground() ) 1149cdf0e10cSrcweir { 1150cdf0e10cSrcweir ImplControlValue aControlValue; 1151cdf0e10cSrcweir Point aGcc3WorkaroundTemporary; 1152cdf0e10cSrcweir Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() ); 1153cdf0e10cSrcweir ControlState nState = 0; 1154cdf0e10cSrcweir 1155cdf0e10cSrcweir if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED; 1156cdf0e10cSrcweir bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion, 1157cdf0e10cSrcweir nState, aControlValue, rtl::OUString() ); 1158cdf0e10cSrcweir } 1159cdf0e10cSrcweir } 1160cdf0e10cSrcweir 1161cdf0e10cSrcweir if ( mbBackground && ! bNativeOK ) 1162cdf0e10cSrcweir { 1163cdf0e10cSrcweir RasterOp eRasterOp = GetRasterOp(); 1164cdf0e10cSrcweir if ( eRasterOp != ROP_OVERPAINT ) 1165cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT ); 1166cdf0e10cSrcweir ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground ); 1167cdf0e10cSrcweir if ( eRasterOp != ROP_OVERPAINT ) 1168cdf0e10cSrcweir SetRasterOp( eRasterOp ); 1169cdf0e10cSrcweir } 1170cdf0e10cSrcweir 1171cdf0e10cSrcweir if( mpAlphaVDev ) 1172cdf0e10cSrcweir mpAlphaVDev->Erase(); 1173cdf0e10cSrcweir } 1174cdf0e10cSrcweir 1175cdf0e10cSrcweir // ----------------------------------------------------------------------- 1176cdf0e10cSrcweir 1177cdf0e10cSrcweir void OutputDevice::ImplDraw2ColorFrame( const Rectangle& rRect, 1178cdf0e10cSrcweir const Color& rLeftTopColor, 1179cdf0e10cSrcweir const Color& rRightBottomColor ) 1180cdf0e10cSrcweir { 1181cdf0e10cSrcweir SetFillColor( rLeftTopColor ); 1182cdf0e10cSrcweir DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Left(), rRect.Bottom()-1 ) ) ); 1183cdf0e10cSrcweir DrawRect( Rectangle( rRect.TopLeft(), Point( rRect.Right()-1, rRect.Top() ) ) ); 1184cdf0e10cSrcweir SetFillColor( rRightBottomColor ); 1185cdf0e10cSrcweir DrawRect( Rectangle( rRect.BottomLeft(), rRect.BottomRight() ) ); 1186cdf0e10cSrcweir DrawRect( Rectangle( rRect.TopRight(), rRect.BottomRight() ) ); 1187cdf0e10cSrcweir } 1188cdf0e10cSrcweir 1189cdf0e10cSrcweir // ----------------------------------------------------------------------- 1190cdf0e10cSrcweir 1191cdf0e10cSrcweir bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize, 1192cdf0e10cSrcweir const GfxLink& rGfxLink, GDIMetaFile* pSubst ) 1193cdf0e10cSrcweir { 1194cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawEPS()" ); 1195cdf0e10cSrcweir 1196cdf0e10cSrcweir bool bDrawn(true); 1197cdf0e10cSrcweir 1198cdf0e10cSrcweir if ( mpMetaFile ) 1199cdf0e10cSrcweir { 1200cdf0e10cSrcweir GDIMetaFile aSubst; 1201cdf0e10cSrcweir 1202cdf0e10cSrcweir if( pSubst ) 1203cdf0e10cSrcweir aSubst = *pSubst; 1204cdf0e10cSrcweir 1205cdf0e10cSrcweir mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) ); 1206cdf0e10cSrcweir } 1207cdf0e10cSrcweir 1208cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1209cdf0e10cSrcweir return bDrawn; 1210cdf0e10cSrcweir 1211cdf0e10cSrcweir if( mbOutputClipped ) 1212cdf0e10cSrcweir return bDrawn; 1213cdf0e10cSrcweir 1214cdf0e10cSrcweir Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) ); 1215cdf0e10cSrcweir 1216cdf0e10cSrcweir if( !aRect.IsEmpty() ) 1217cdf0e10cSrcweir { 1218cdf0e10cSrcweir // draw the real EPS graphics 1219cdf0e10cSrcweir if( rGfxLink.GetData() && rGfxLink.GetDataSize() ) 1220cdf0e10cSrcweir { 1221cdf0e10cSrcweir if( !mpGraphics && !ImplGetGraphics() ) 1222cdf0e10cSrcweir return bDrawn; 1223cdf0e10cSrcweir 1224cdf0e10cSrcweir if( mbInitClipRegion ) 1225cdf0e10cSrcweir ImplInitClipRegion(); 1226cdf0e10cSrcweir 1227cdf0e10cSrcweir aRect.Justify(); 1228cdf0e10cSrcweir bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), 1229cdf0e10cSrcweir (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this ); 1230cdf0e10cSrcweir } 1231cdf0e10cSrcweir 1232cdf0e10cSrcweir // else draw the substitution graphics 1233cdf0e10cSrcweir if( !bDrawn && pSubst ) 1234cdf0e10cSrcweir { 1235cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 1236cdf0e10cSrcweir 1237cdf0e10cSrcweir mpMetaFile = NULL; 1238cdf0e10cSrcweir Graphic( *pSubst ).Draw( this, rPoint, rSize ); 1239cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 1240cdf0e10cSrcweir } 1241cdf0e10cSrcweir } 1242cdf0e10cSrcweir 1243cdf0e10cSrcweir if( mpAlphaVDev ) 1244cdf0e10cSrcweir mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst ); 1245cdf0e10cSrcweir 1246cdf0e10cSrcweir return bDrawn; 1247cdf0e10cSrcweir } 1248cdf0e10cSrcweir 1249cdf0e10cSrcweir // ------------------------------------------------------------------ 1250cdf0e10cSrcweir 1251cdf0e10cSrcweir void OutputDevice::DrawRenderGraphic( const Point& rPoint, const Size& rSize, 1252cdf0e10cSrcweir const ::vcl::RenderGraphic& rRenderGraphic ) 1253cdf0e10cSrcweir { 1254cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawRenderGraphic()" ); 1255cdf0e10cSrcweir 1256cdf0e10cSrcweir if( mpMetaFile ) 1257cdf0e10cSrcweir mpMetaFile->AddAction( new MetaRenderGraphicAction( rPoint, rSize, rRenderGraphic ) ); 1258cdf0e10cSrcweir 1259cdf0e10cSrcweir if( !rRenderGraphic.IsEmpty() ) 1260cdf0e10cSrcweir { 1261cdf0e10cSrcweir ::vcl::RenderGraphicRasterizer aRasterizer( rRenderGraphic ); 1262cdf0e10cSrcweir BitmapEx aBmpEx; 1263cdf0e10cSrcweir const Size aSizePixel( LogicToPixel( rSize ) ); 1264cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 1265cdf0e10cSrcweir 1266cdf0e10cSrcweir mpMetaFile = NULL; 1267cdf0e10cSrcweir DrawBitmapEx( rPoint, rSize, aRasterizer.Rasterize( aSizePixel ) ); 1268cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 1269cdf0e10cSrcweir } 1270cdf0e10cSrcweir } 1271