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