1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_vcl.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <tools/debug.hxx> 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include <vcl/bitmap.hxx> 34*cdf0e10cSrcweir #include <vcl/bitmapex.hxx> 35*cdf0e10cSrcweir #include <vcl/window.hxx> 36*cdf0e10cSrcweir #include <vcl/metaact.hxx> 37*cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 38*cdf0e10cSrcweir #include <vcl/virdev.hxx> 39*cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 40*cdf0e10cSrcweir #include <vcl/outdev.hxx> 41*cdf0e10cSrcweir #include <vcl/window.hxx> 42*cdf0e10cSrcweir #include <vcl/image.hxx> 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir #include <bmpfast.hxx> 45*cdf0e10cSrcweir #include <salbmp.hxx> 46*cdf0e10cSrcweir #include <salgdi.hxx> 47*cdf0e10cSrcweir #include <impbmp.hxx> 48*cdf0e10cSrcweir #include <sallayout.hxx> 49*cdf0e10cSrcweir #include <image.h> 50*cdf0e10cSrcweir #include <outdev.h> 51*cdf0e10cSrcweir #include <window.h> 52*cdf0e10cSrcweir #include <region.h> 53*cdf0e10cSrcweir #include <outdata.hxx> 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir #define BAND_MAX_SIZE 512000 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir // ======================================================================= 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir DBG_NAMEEX( OutputDevice ) 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir // ======================================================================= 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir // ----------- 64*cdf0e10cSrcweir // - Defines - 65*cdf0e10cSrcweir // ----------- 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir #define OUTDEV_INIT() \ 68*cdf0e10cSrcweir { \ 69*cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() ) \ 70*cdf0e10cSrcweir return; \ 71*cdf0e10cSrcweir \ 72*cdf0e10cSrcweir if ( !mpGraphics ) \ 73*cdf0e10cSrcweir if ( !ImplGetGraphics() ) \ 74*cdf0e10cSrcweir return; \ 75*cdf0e10cSrcweir \ 76*cdf0e10cSrcweir if ( mbInitClipRegion ) \ 77*cdf0e10cSrcweir ImplInitClipRegion(); \ 78*cdf0e10cSrcweir \ 79*cdf0e10cSrcweir if ( mbOutputClipped ) \ 80*cdf0e10cSrcweir return; \ 81*cdf0e10cSrcweir } 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir #define TwoRect SalTwoRect 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir // ------------- 86*cdf0e10cSrcweir // - externals - 87*cdf0e10cSrcweir // ------------- 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir extern sal_uLong nVCLRLut[ 6 ]; 90*cdf0e10cSrcweir extern sal_uLong nVCLGLut[ 6 ]; 91*cdf0e10cSrcweir extern sal_uLong nVCLBLut[ 6 ]; 92*cdf0e10cSrcweir extern sal_uLong nVCLDitherLut[ 256 ]; 93*cdf0e10cSrcweir extern sal_uLong nVCLLut[ 256 ]; 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir // ======================================================================= 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir sal_uLong ImplAdjustTwoRect( TwoRect& rTwoRect, const Size& rSizePix ) 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir sal_uLong nMirrFlags = 0; 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir if ( rTwoRect.mnDestWidth < 0 ) 102*cdf0e10cSrcweir { 103*cdf0e10cSrcweir rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth; 104*cdf0e10cSrcweir rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth; 105*cdf0e10cSrcweir rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1; 106*cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ; 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir if ( rTwoRect.mnDestHeight < 0 ) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight; 112*cdf0e10cSrcweir rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight; 113*cdf0e10cSrcweir rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1; 114*cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT; 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) || 118*cdf0e10cSrcweir ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) || 119*cdf0e10cSrcweir ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) || 120*cdf0e10cSrcweir ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) ) 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ), 123*cdf0e10cSrcweir Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) ); 124*cdf0e10cSrcweir Rectangle aCropRect( aSourceRect ); 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir aCropRect.Intersection( Rectangle( Point(), rSizePix ) ); 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir if( aCropRect.IsEmpty() ) 129*cdf0e10cSrcweir rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0; 130*cdf0e10cSrcweir else 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0; 133*cdf0e10cSrcweir const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) ); 136*cdf0e10cSrcweir const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) ); 137*cdf0e10cSrcweir const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) ); 138*cdf0e10cSrcweir const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) ); 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir rTwoRect.mnSrcX = aCropRect.Left(); 141*cdf0e10cSrcweir rTwoRect.mnSrcY = aCropRect.Top(); 142*cdf0e10cSrcweir rTwoRect.mnSrcWidth = aCropRect.GetWidth(); 143*cdf0e10cSrcweir rTwoRect.mnSrcHeight = aCropRect.GetHeight(); 144*cdf0e10cSrcweir rTwoRect.mnDestX = nDstX1; 145*cdf0e10cSrcweir rTwoRect.mnDestY = nDstY1; 146*cdf0e10cSrcweir rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1; 147*cdf0e10cSrcweir rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1; 148*cdf0e10cSrcweir } 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir return nMirrFlags; 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir // ======================================================================= 155*cdf0e10cSrcweir 156*cdf0e10cSrcweir void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, void* pVoidPosAry ) 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir TwoRect* pPosAry = (TwoRect*)pVoidPosAry; 159*cdf0e10cSrcweir SalGraphics* pGraphics2; 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir if ( pPosAry->mnSrcWidth && pPosAry->mnSrcHeight && pPosAry->mnDestWidth && pPosAry->mnDestHeight ) 162*cdf0e10cSrcweir { 163*cdf0e10cSrcweir if ( this == pSrcDev ) 164*cdf0e10cSrcweir pGraphics2 = NULL; 165*cdf0e10cSrcweir else 166*cdf0e10cSrcweir { 167*cdf0e10cSrcweir if ( (GetOutDevType() != pSrcDev->GetOutDevType()) || 168*cdf0e10cSrcweir (GetOutDevType() != OUTDEV_WINDOW) ) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir if ( !pSrcDev->mpGraphics ) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() ) 173*cdf0e10cSrcweir return; 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir pGraphics2 = pSrcDev->mpGraphics; 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir else 178*cdf0e10cSrcweir { 179*cdf0e10cSrcweir if ( ((Window*)this)->mpWindowImpl->mpFrameWindow == ((Window*)pSrcDev)->mpWindowImpl->mpFrameWindow ) 180*cdf0e10cSrcweir pGraphics2 = NULL; 181*cdf0e10cSrcweir else 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir if ( !pSrcDev->mpGraphics ) 184*cdf0e10cSrcweir { 185*cdf0e10cSrcweir if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() ) 186*cdf0e10cSrcweir return; 187*cdf0e10cSrcweir } 188*cdf0e10cSrcweir pGraphics2 = pSrcDev->mpGraphics; 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir if ( !mpGraphics ) 191*cdf0e10cSrcweir { 192*cdf0e10cSrcweir if ( !ImplGetGraphics() ) 193*cdf0e10cSrcweir return; 194*cdf0e10cSrcweir } 195*cdf0e10cSrcweir DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics, 196*cdf0e10cSrcweir "OutputDevice::DrawOutDev(): We need more than one Graphics" ); 197*cdf0e10cSrcweir } 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir // #102532# Offset only has to be pseudo window offset 202*cdf0e10cSrcweir Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ), 203*cdf0e10cSrcweir Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) ); 204*cdf0e10cSrcweir Rectangle aSrcRect( Point( pPosAry->mnSrcX, pPosAry->mnSrcY ), 205*cdf0e10cSrcweir Size( pPosAry->mnSrcWidth, pPosAry->mnSrcHeight ) ); 206*cdf0e10cSrcweir const long nOldRight = aSrcRect.Right(); 207*cdf0e10cSrcweir const long nOldBottom = aSrcRect.Bottom(); 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() ) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir if ( (pPosAry->mnSrcX+pPosAry->mnSrcWidth-1) > aSrcOutRect.Right() ) 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir const long nOldWidth = pPosAry->mnSrcWidth; 214*cdf0e10cSrcweir pPosAry->mnSrcWidth -= (nOldRight - aSrcRect.Right()); 215*cdf0e10cSrcweir pPosAry->mnDestWidth = pPosAry->mnDestWidth * pPosAry->mnSrcWidth / nOldWidth; 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir if ( (pPosAry->mnSrcY+pPosAry->mnSrcHeight-1) > aSrcOutRect.Bottom() ) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir const long nOldHeight = pPosAry->mnSrcHeight; 221*cdf0e10cSrcweir pPosAry->mnSrcHeight -= (nOldBottom - aSrcRect.Bottom()); 222*cdf0e10cSrcweir pPosAry->mnDestHeight = pPosAry->mnDestHeight * pPosAry->mnSrcHeight / nOldHeight; 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir // --- RTL --- if this is no window, but pSrcDev is a window 226*cdf0e10cSrcweir // mirroring may be required 227*cdf0e10cSrcweir // because only windows have a SalGraphicsLayout 228*cdf0e10cSrcweir // mirroring is performed here 229*cdf0e10cSrcweir if( (GetOutDevType() != OUTDEV_WINDOW) && pGraphics2 && (pGraphics2->GetLayout() & SAL_LAYOUT_BIDI_RTL) ) 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir SalTwoRect pPosAry2 = *pPosAry; 232*cdf0e10cSrcweir pGraphics2->mirror( pPosAry2.mnSrcX, pPosAry2.mnSrcWidth, pSrcDev ); 233*cdf0e10cSrcweir mpGraphics->CopyBits( &pPosAry2, pGraphics2, this, pSrcDev ); 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir else 236*cdf0e10cSrcweir mpGraphics->CopyBits( pPosAry, pGraphics2, this, pSrcDev ); 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir } 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir // ------------------------------------------------------------------ 242*cdf0e10cSrcweir 243*cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize, 244*cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize ) 245*cdf0e10cSrcweir { 246*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawOutDev()" ); 247*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 248*cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" ); 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 251*cdf0e10cSrcweir return; 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir if ( meOutDevType == OUTDEV_PRINTER ) 254*cdf0e10cSrcweir return; 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir if ( ROP_INVERT == meRasterOp ) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 259*cdf0e10cSrcweir return; 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir if ( mpMetaFile ) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) ); 265*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) ); 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir OUTDEV_INIT(); 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir TwoRect aPosAry; 271*cdf0e10cSrcweir aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() ); 272*cdf0e10cSrcweir aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() ); 273*cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 274*cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 277*cdf0e10cSrcweir { 278*cdf0e10cSrcweir aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() ); 279*cdf0e10cSrcweir aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() ); 280*cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 281*cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ), 284*cdf0e10cSrcweir Size( mnOutWidth, mnOutHeight ) ); 285*cdf0e10cSrcweir Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ), 286*cdf0e10cSrcweir Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) ); 287*cdf0e10cSrcweir long nOldRight = aSrcRect.Right(); 288*cdf0e10cSrcweir long nOldBottom = aSrcRect.Bottom(); 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() ) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() ) 293*cdf0e10cSrcweir { 294*cdf0e10cSrcweir long nOldWidth = aPosAry.mnSrcWidth; 295*cdf0e10cSrcweir aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right(); 296*cdf0e10cSrcweir aPosAry.mnDestWidth = aPosAry.mnDestWidth*aPosAry.mnSrcWidth/nOldWidth; 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() ) 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir long nOldHeight = aPosAry.mnSrcHeight; 302*cdf0e10cSrcweir aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom(); 303*cdf0e10cSrcweir aPosAry.mnDestHeight = aPosAry.mnDestHeight*aPosAry.mnSrcHeight/nOldHeight; 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir 306*cdf0e10cSrcweir mpGraphics->CopyBits( &aPosAry, NULL, this, NULL ); 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir if( mpAlphaVDev ) 311*cdf0e10cSrcweir mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize ); 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir // ------------------------------------------------------------------ 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize, 317*cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize, 318*cdf0e10cSrcweir const OutputDevice& rOutDev ) 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawOutDev()" ); 321*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 322*cdf0e10cSrcweir DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice ); 323*cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" ); 324*cdf0e10cSrcweir DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" ); 325*cdf0e10cSrcweir 326*cdf0e10cSrcweir if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) || ImplIsRecordLayout() ) 327*cdf0e10cSrcweir return; 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir if ( ROP_INVERT == meRasterOp ) 330*cdf0e10cSrcweir { 331*cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 332*cdf0e10cSrcweir return; 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir if ( mpMetaFile ) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) ); 338*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) ); 339*cdf0e10cSrcweir } 340*cdf0e10cSrcweir 341*cdf0e10cSrcweir OUTDEV_INIT(); 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir TwoRect aPosAry; 344*cdf0e10cSrcweir aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() ); 345*cdf0e10cSrcweir aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() ); 346*cdf0e10cSrcweir aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() ); 347*cdf0e10cSrcweir aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() ); 348*cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 349*cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 350*cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 351*cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir if( mpAlphaVDev ) 354*cdf0e10cSrcweir { 355*cdf0e10cSrcweir if( rOutDev.mpAlphaVDev ) 356*cdf0e10cSrcweir { 357*cdf0e10cSrcweir // alpha-blend source over destination 358*cdf0e10cSrcweir DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) ); 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir // This would be mode SOURCE: 361*cdf0e10cSrcweir // copy source alpha channel to our alpha channel 362*cdf0e10cSrcweir //mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev ); 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir else 365*cdf0e10cSrcweir { 366*cdf0e10cSrcweir ImplDrawOutDevDirect( &rOutDev, &aPosAry ); 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir // #i32109#: make destination rectangle opaque - source has no alpha 369*cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 370*cdf0e10cSrcweir } 371*cdf0e10cSrcweir } 372*cdf0e10cSrcweir else 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir if( rOutDev.mpAlphaVDev ) 375*cdf0e10cSrcweir { 376*cdf0e10cSrcweir // alpha-blend source over destination 377*cdf0e10cSrcweir DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) ); 378*cdf0e10cSrcweir } 379*cdf0e10cSrcweir else 380*cdf0e10cSrcweir { 381*cdf0e10cSrcweir // no alpha at all, neither in source nor destination device 382*cdf0e10cSrcweir ImplDrawOutDevDirect( &rOutDev, &aPosAry ); 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir } 385*cdf0e10cSrcweir } 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir // ------------------------------------------------------------------ 388*cdf0e10cSrcweir 389*cdf0e10cSrcweir void OutputDevice::CopyArea( const Point& rDestPt, 390*cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize, 391*cdf0e10cSrcweir sal_uInt16 nFlags ) 392*cdf0e10cSrcweir { 393*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::CopyArea()" ); 394*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 395*cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" ); 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir if ( meOutDevType == OUTDEV_PRINTER || ImplIsRecordLayout() ) 398*cdf0e10cSrcweir return; 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir RasterOp eOldRop = GetRasterOp(); 401*cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT ); 402*cdf0e10cSrcweir 403*cdf0e10cSrcweir OUTDEV_INIT(); 404*cdf0e10cSrcweir 405*cdf0e10cSrcweir TwoRect aPosAry; 406*cdf0e10cSrcweir aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() ); 407*cdf0e10cSrcweir aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() ); 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight ) 410*cdf0e10cSrcweir { 411*cdf0e10cSrcweir aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() ); 412*cdf0e10cSrcweir aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() ); 413*cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 414*cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 415*cdf0e10cSrcweir 416*cdf0e10cSrcweir Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ), 417*cdf0e10cSrcweir Size( mnOutWidth, mnOutHeight ) ); 418*cdf0e10cSrcweir Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ), 419*cdf0e10cSrcweir Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) ); 420*cdf0e10cSrcweir long nOldRight = aSrcRect.Right(); 421*cdf0e10cSrcweir long nOldBottom = aSrcRect.Bottom(); 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() ) 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() ) 426*cdf0e10cSrcweir aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right(); 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() ) 429*cdf0e10cSrcweir aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom(); 430*cdf0e10cSrcweir 431*cdf0e10cSrcweir if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) ) 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir ((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect, 434*cdf0e10cSrcweir aPosAry.mnDestX-aPosAry.mnSrcX, 435*cdf0e10cSrcweir aPosAry.mnDestY-aPosAry.mnSrcY, 436*cdf0e10cSrcweir sal_False ); 437*cdf0e10cSrcweir 438*cdf0e10cSrcweir mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY, 439*cdf0e10cSrcweir aPosAry.mnSrcX, aPosAry.mnSrcY, 440*cdf0e10cSrcweir aPosAry.mnSrcWidth, aPosAry.mnSrcHeight, 441*cdf0e10cSrcweir SAL_COPYAREA_WINDOWINVALIDATE, this ); 442*cdf0e10cSrcweir } 443*cdf0e10cSrcweir else 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir aPosAry.mnDestWidth = aPosAry.mnSrcWidth; 446*cdf0e10cSrcweir aPosAry.mnDestHeight = aPosAry.mnSrcHeight; 447*cdf0e10cSrcweir mpGraphics->CopyBits( &aPosAry, NULL, this, NULL ); 448*cdf0e10cSrcweir } 449*cdf0e10cSrcweir } 450*cdf0e10cSrcweir } 451*cdf0e10cSrcweir 452*cdf0e10cSrcweir SetRasterOp( eOldRop ); 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir if( mpAlphaVDev ) 455*cdf0e10cSrcweir mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags ); 456*cdf0e10cSrcweir } 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir // ------------------------------------------------------------------ 459*cdf0e10cSrcweir 460*cdf0e10cSrcweir void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize, 461*cdf0e10cSrcweir const OutputDevice& rOutDev, const Region& rRegion ) 462*cdf0e10cSrcweir { 463*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 466*cdf0e10cSrcweir sal_Bool bOldMap = mbMap; 467*cdf0e10cSrcweir RasterOp eOldROP = GetRasterOp(); 468*cdf0e10cSrcweir mpMetaFile = NULL; 469*cdf0e10cSrcweir mbMap = sal_False; 470*cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT ); 471*cdf0e10cSrcweir 472*cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() ) 473*cdf0e10cSrcweir return; 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir if ( !mpGraphics ) 476*cdf0e10cSrcweir { 477*cdf0e10cSrcweir if ( !ImplGetGraphics() ) 478*cdf0e10cSrcweir return; 479*cdf0e10cSrcweir } 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir // ClipRegion zuruecksetzen 482*cdf0e10cSrcweir if ( rRegion.IsNull() ) 483*cdf0e10cSrcweir mpGraphics->ResetClipRegion(); 484*cdf0e10cSrcweir else 485*cdf0e10cSrcweir ImplSelectClipRegion( rRegion ); 486*cdf0e10cSrcweir 487*cdf0e10cSrcweir TwoRect aPosAry; 488*cdf0e10cSrcweir aPosAry.mnSrcX = rDevPt.X(); 489*cdf0e10cSrcweir aPosAry.mnSrcY = rDevPt.Y(); 490*cdf0e10cSrcweir aPosAry.mnSrcWidth = rDevSize.Width(); 491*cdf0e10cSrcweir aPosAry.mnSrcHeight = rDevSize.Height(); 492*cdf0e10cSrcweir aPosAry.mnDestX = rPt.X(); 493*cdf0e10cSrcweir aPosAry.mnDestY = rPt.Y(); 494*cdf0e10cSrcweir aPosAry.mnDestWidth = rDevSize.Width(); 495*cdf0e10cSrcweir aPosAry.mnDestHeight = rDevSize.Height(); 496*cdf0e10cSrcweir ImplDrawOutDevDirect( &rOutDev, &aPosAry ); 497*cdf0e10cSrcweir 498*cdf0e10cSrcweir // Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird 499*cdf0e10cSrcweir mbInitClipRegion = sal_True; 500*cdf0e10cSrcweir 501*cdf0e10cSrcweir SetRasterOp( eOldROP ); 502*cdf0e10cSrcweir mbMap = bOldMap; 503*cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 504*cdf0e10cSrcweir } 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir // ------------------------------------------------------------------ 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize, 509*cdf0e10cSrcweir OutputDevice& rDev ) 510*cdf0e10cSrcweir { 511*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir sal_Bool bOldMap = mbMap; 514*cdf0e10cSrcweir mbMap = sal_False; 515*cdf0e10cSrcweir rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this ); 516*cdf0e10cSrcweir mbMap = bOldMap; 517*cdf0e10cSrcweir } 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir // ------------------------------------------------------------------ 520*cdf0e10cSrcweir 521*cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap ) 522*cdf0e10cSrcweir { 523*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap()" ); 524*cdf0e10cSrcweir 525*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 526*cdf0e10cSrcweir return; 527*cdf0e10cSrcweir 528*cdf0e10cSrcweir const Size aSizePix( rBitmap.GetSizePixel() ); 529*cdf0e10cSrcweir ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION ); 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir if( mpAlphaVDev ) 532*cdf0e10cSrcweir { 533*cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 534*cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, PixelToLogic( aSizePix )) ); 535*cdf0e10cSrcweir } 536*cdf0e10cSrcweir } 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir // ------------------------------------------------------------------ 539*cdf0e10cSrcweir 540*cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap ) 541*cdf0e10cSrcweir { 542*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap( Size )" ); 543*cdf0e10cSrcweir 544*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 545*cdf0e10cSrcweir return; 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION ); 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir if( mpAlphaVDev ) 550*cdf0e10cSrcweir { 551*cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 552*cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 553*cdf0e10cSrcweir } 554*cdf0e10cSrcweir } 555*cdf0e10cSrcweir 556*cdf0e10cSrcweir // ------------------------------------------------------------------ 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, 559*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 560*cdf0e10cSrcweir const Bitmap& rBitmap ) 561*cdf0e10cSrcweir { 562*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" ); 563*cdf0e10cSrcweir 564*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 565*cdf0e10cSrcweir return; 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION ); 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir if( mpAlphaVDev ) 570*cdf0e10cSrcweir { 571*cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 572*cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 573*cdf0e10cSrcweir } 574*cdf0e10cSrcweir } 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 577*cdf0e10cSrcweir 578*cdf0e10cSrcweir void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize, 579*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 580*cdf0e10cSrcweir const Bitmap& rBitmap, const sal_uLong nAction ) 581*cdf0e10cSrcweir { 582*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 583*cdf0e10cSrcweir 584*cdf0e10cSrcweir Bitmap aBmp( rBitmap ); 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) ) 587*cdf0e10cSrcweir return; 588*cdf0e10cSrcweir else if ( ROP_INVERT == meRasterOp ) 589*cdf0e10cSrcweir { 590*cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 591*cdf0e10cSrcweir return; 592*cdf0e10cSrcweir } 593*cdf0e10cSrcweir else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | 594*cdf0e10cSrcweir DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) ) 595*cdf0e10cSrcweir { 596*cdf0e10cSrcweir if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) ) 597*cdf0e10cSrcweir { 598*cdf0e10cSrcweir sal_uInt8 cCmpVal; 599*cdf0e10cSrcweir 600*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_BLACKBITMAP ) 601*cdf0e10cSrcweir cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0; 602*cdf0e10cSrcweir else 603*cdf0e10cSrcweir cCmpVal = 255; 604*cdf0e10cSrcweir 605*cdf0e10cSrcweir Color aCol( cCmpVal, cCmpVal, cCmpVal ); 606*cdf0e10cSrcweir Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 607*cdf0e10cSrcweir SetLineColor( aCol ); 608*cdf0e10cSrcweir SetFillColor( aCol ); 609*cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 610*cdf0e10cSrcweir Pop(); 611*cdf0e10cSrcweir return; 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir else if( !!aBmp ) 614*cdf0e10cSrcweir { 615*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GRAYBITMAP ) 616*cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_8BIT_GREYS ); 617*cdf0e10cSrcweir 618*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) 619*cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_GHOSTED ); 620*cdf0e10cSrcweir } 621*cdf0e10cSrcweir } 622*cdf0e10cSrcweir 623*cdf0e10cSrcweir if ( mpMetaFile ) 624*cdf0e10cSrcweir { 625*cdf0e10cSrcweir switch( nAction ) 626*cdf0e10cSrcweir { 627*cdf0e10cSrcweir case( META_BMP_ACTION ): 628*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) ); 629*cdf0e10cSrcweir break; 630*cdf0e10cSrcweir 631*cdf0e10cSrcweir case( META_BMPSCALE_ACTION ): 632*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) ); 633*cdf0e10cSrcweir break; 634*cdf0e10cSrcweir 635*cdf0e10cSrcweir case( META_BMPSCALEPART_ACTION ): 636*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScalePartAction( 637*cdf0e10cSrcweir rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) ); 638*cdf0e10cSrcweir break; 639*cdf0e10cSrcweir } 640*cdf0e10cSrcweir } 641*cdf0e10cSrcweir 642*cdf0e10cSrcweir OUTDEV_INIT(); 643*cdf0e10cSrcweir 644*cdf0e10cSrcweir if( !aBmp.IsEmpty() ) 645*cdf0e10cSrcweir { 646*cdf0e10cSrcweir TwoRect aPosAry; 647*cdf0e10cSrcweir 648*cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X(); 649*cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y(); 650*cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width(); 651*cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height(); 652*cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 653*cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 654*cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 655*cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 656*cdf0e10cSrcweir 657*cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() ); 658*cdf0e10cSrcweir 659*cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 660*cdf0e10cSrcweir { 661*cdf0e10cSrcweir if ( nMirrFlags ) 662*cdf0e10cSrcweir aBmp.Mirror( nMirrFlags ); 663*cdf0e10cSrcweir 664*cdf0e10cSrcweir /* #i75264# (corrected with #i81576#) 665*cdf0e10cSrcweir * sometimes a bitmap is scaled to a ridiculous size and drawn 666*cdf0e10cSrcweir * to a quite normal VDev, so only a very small part of 667*cdf0e10cSrcweir * the scaled bitmap will be visible. However actually scaling 668*cdf0e10cSrcweir * the bitmap will use so much memory that we end with a crash. 669*cdf0e10cSrcweir * Workaround: since only a small part of the scaled bitmap will 670*cdf0e10cSrcweir * be actually drawn anyway (because of clipping on the device 671*cdf0e10cSrcweir * boundary), limit the destination and source rectangles so 672*cdf0e10cSrcweir * that the destination rectangle will overlap the device but only 673*cdf0e10cSrcweir * be reasonably (say factor 2) larger than the device itself. 674*cdf0e10cSrcweir */ 675*cdf0e10cSrcweir if( aPosAry.mnDestWidth > 2048 || aPosAry.mnDestHeight > 2048 ) 676*cdf0e10cSrcweir { 677*cdf0e10cSrcweir if( meOutDevType == OUTDEV_WINDOW || 678*cdf0e10cSrcweir (meOutDevType == OUTDEV_VIRDEV && mpPDFWriter == 0 ) ) 679*cdf0e10cSrcweir { 680*cdf0e10cSrcweir // #i81576# do the following trick only if there is overlap at all 681*cdf0e10cSrcweir // else the formulae don't work 682*cdf0e10cSrcweir // theoretically in this case we wouldn't need to draw the bitmap at all 683*cdf0e10cSrcweir // however there are some esoteric case where that is needed 684*cdf0e10cSrcweir if( aPosAry.mnDestX + aPosAry.mnDestWidth >= 0 685*cdf0e10cSrcweir && aPosAry.mnDestX < mnOutWidth 686*cdf0e10cSrcweir && aPosAry.mnDestY + aPosAry.mnDestHeight >= 0 687*cdf0e10cSrcweir && aPosAry.mnDestY < mnOutHeight ) 688*cdf0e10cSrcweir { 689*cdf0e10cSrcweir // reduce scaling to something reasonable taking into account the output size 690*cdf0e10cSrcweir if( aPosAry.mnDestWidth > 3*mnOutWidth && aPosAry.mnSrcWidth ) 691*cdf0e10cSrcweir { 692*cdf0e10cSrcweir const double nScaleX = aPosAry.mnDestWidth/double(aPosAry.mnSrcWidth); 693*cdf0e10cSrcweir 694*cdf0e10cSrcweir if( aPosAry.mnDestX + aPosAry.mnDestWidth > mnOutWidth ) 695*cdf0e10cSrcweir { 696*cdf0e10cSrcweir aPosAry.mnDestWidth = Max(long(0),mnOutWidth-aPosAry.mnDestX); 697*cdf0e10cSrcweir } 698*cdf0e10cSrcweir if( aPosAry.mnDestX < 0 ) 699*cdf0e10cSrcweir { 700*cdf0e10cSrcweir aPosAry.mnDestWidth += aPosAry.mnDestX; 701*cdf0e10cSrcweir aPosAry.mnSrcX -= sal::static_int_cast<long>(aPosAry.mnDestX / nScaleX); 702*cdf0e10cSrcweir aPosAry.mnDestX = 0; 703*cdf0e10cSrcweir } 704*cdf0e10cSrcweir 705*cdf0e10cSrcweir aPosAry.mnSrcWidth = sal::static_int_cast<long>(aPosAry.mnDestWidth / nScaleX); 706*cdf0e10cSrcweir } 707*cdf0e10cSrcweir 708*cdf0e10cSrcweir if( aPosAry.mnDestHeight > 3*mnOutHeight && aPosAry.mnSrcHeight != 0 ) 709*cdf0e10cSrcweir { 710*cdf0e10cSrcweir const double nScaleY = aPosAry.mnDestHeight/double(aPosAry.mnSrcHeight); 711*cdf0e10cSrcweir 712*cdf0e10cSrcweir if( aPosAry.mnDestY + aPosAry.mnDestHeight > mnOutHeight ) 713*cdf0e10cSrcweir { 714*cdf0e10cSrcweir aPosAry.mnDestHeight = Max(long(0),mnOutHeight-aPosAry.mnDestY); 715*cdf0e10cSrcweir } 716*cdf0e10cSrcweir if( aPosAry.mnDestY < 0 ) 717*cdf0e10cSrcweir { 718*cdf0e10cSrcweir aPosAry.mnDestHeight += aPosAry.mnDestY; 719*cdf0e10cSrcweir aPosAry.mnSrcY -= sal::static_int_cast<long>(aPosAry.mnDestY / nScaleY); 720*cdf0e10cSrcweir aPosAry.mnDestY = 0; 721*cdf0e10cSrcweir } 722*cdf0e10cSrcweir 723*cdf0e10cSrcweir aPosAry.mnSrcHeight = sal::static_int_cast<long>(aPosAry.mnDestHeight / nScaleY); 724*cdf0e10cSrcweir } 725*cdf0e10cSrcweir } 726*cdf0e10cSrcweir } 727*cdf0e10cSrcweir } 728*cdf0e10cSrcweir 729*cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 730*cdf0e10cSrcweir mpGraphics->DrawBitmap( &aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this ); 731*cdf0e10cSrcweir } 732*cdf0e10cSrcweir } 733*cdf0e10cSrcweir } 734*cdf0e10cSrcweir 735*cdf0e10cSrcweir // ------------------------------------------------------------------ 736*cdf0e10cSrcweir 737*cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, 738*cdf0e10cSrcweir const BitmapEx& rBitmapEx ) 739*cdf0e10cSrcweir { 740*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx()" ); 741*cdf0e10cSrcweir 742*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 743*cdf0e10cSrcweir return; 744*cdf0e10cSrcweir 745*cdf0e10cSrcweir if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() ) 746*cdf0e10cSrcweir DrawBitmap( rDestPt, rBitmapEx.GetBitmap() ); 747*cdf0e10cSrcweir else 748*cdf0e10cSrcweir { 749*cdf0e10cSrcweir const Size aSizePix( rBitmapEx.GetSizePixel() ); 750*cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION ); 751*cdf0e10cSrcweir } 752*cdf0e10cSrcweir } 753*cdf0e10cSrcweir 754*cdf0e10cSrcweir // ------------------------------------------------------------------ 755*cdf0e10cSrcweir 756*cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize, 757*cdf0e10cSrcweir const BitmapEx& rBitmapEx ) 758*cdf0e10cSrcweir { 759*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" ); 760*cdf0e10cSrcweir 761*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 762*cdf0e10cSrcweir return; 763*cdf0e10cSrcweir 764*cdf0e10cSrcweir if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() ) 765*cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() ); 766*cdf0e10cSrcweir else 767*cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION ); 768*cdf0e10cSrcweir } 769*cdf0e10cSrcweir 770*cdf0e10cSrcweir // ------------------------------------------------------------------ 771*cdf0e10cSrcweir 772*cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize, 773*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 774*cdf0e10cSrcweir const BitmapEx& rBitmapEx ) 775*cdf0e10cSrcweir { 776*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" ); 777*cdf0e10cSrcweir 778*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 779*cdf0e10cSrcweir return; 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() ) 782*cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() ); 783*cdf0e10cSrcweir else 784*cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION ); 785*cdf0e10cSrcweir } 786*cdf0e10cSrcweir 787*cdf0e10cSrcweir // ------------------------------------------------------------------ 788*cdf0e10cSrcweir 789*cdf0e10cSrcweir void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize, 790*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 791*cdf0e10cSrcweir const BitmapEx& rBitmapEx, const sal_uLong nAction ) 792*cdf0e10cSrcweir { 793*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 794*cdf0e10cSrcweir 795*cdf0e10cSrcweir BitmapEx aBmpEx( rBitmapEx ); 796*cdf0e10cSrcweir 797*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_NOBITMAP ) 798*cdf0e10cSrcweir return; 799*cdf0e10cSrcweir else if ( ROP_INVERT == meRasterOp ) 800*cdf0e10cSrcweir { 801*cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 802*cdf0e10cSrcweir return; 803*cdf0e10cSrcweir } 804*cdf0e10cSrcweir else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | 805*cdf0e10cSrcweir DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) ) 806*cdf0e10cSrcweir { 807*cdf0e10cSrcweir if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) ) 808*cdf0e10cSrcweir { 809*cdf0e10cSrcweir Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 ); 810*cdf0e10cSrcweir sal_uInt8 cCmpVal; 811*cdf0e10cSrcweir 812*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_BLACKBITMAP ) 813*cdf0e10cSrcweir cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0; 814*cdf0e10cSrcweir else 815*cdf0e10cSrcweir cCmpVal = 255; 816*cdf0e10cSrcweir 817*cdf0e10cSrcweir aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) ); 818*cdf0e10cSrcweir 819*cdf0e10cSrcweir if( aBmpEx.IsAlpha() ) 820*cdf0e10cSrcweir { 821*cdf0e10cSrcweir // Create one-bit mask out of alpha channel, by 822*cdf0e10cSrcweir // thresholding it at alpha=0.5. As 823*cdf0e10cSrcweir // DRAWMODE_BLACK/WHITEBITMAP requires monochrome 824*cdf0e10cSrcweir // output, having alpha-induced grey levels is not 825*cdf0e10cSrcweir // acceptable. 826*cdf0e10cSrcweir Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() ); 827*cdf0e10cSrcweir aMask.MakeMono( 128 ); 828*cdf0e10cSrcweir aBmpEx = BitmapEx( aColorBmp, aMask ); 829*cdf0e10cSrcweir } 830*cdf0e10cSrcweir else 831*cdf0e10cSrcweir { 832*cdf0e10cSrcweir aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() ); 833*cdf0e10cSrcweir } 834*cdf0e10cSrcweir } 835*cdf0e10cSrcweir else if( !!aBmpEx ) 836*cdf0e10cSrcweir { 837*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GRAYBITMAP ) 838*cdf0e10cSrcweir aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS ); 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) 841*cdf0e10cSrcweir aBmpEx.Convert( BMP_CONVERSION_GHOSTED ); 842*cdf0e10cSrcweir } 843*cdf0e10cSrcweir } 844*cdf0e10cSrcweir 845*cdf0e10cSrcweir if ( mpMetaFile ) 846*cdf0e10cSrcweir { 847*cdf0e10cSrcweir switch( nAction ) 848*cdf0e10cSrcweir { 849*cdf0e10cSrcweir case( META_BMPEX_ACTION ): 850*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) ); 851*cdf0e10cSrcweir break; 852*cdf0e10cSrcweir 853*cdf0e10cSrcweir case( META_BMPEXSCALE_ACTION ): 854*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) ); 855*cdf0e10cSrcweir break; 856*cdf0e10cSrcweir 857*cdf0e10cSrcweir case( META_BMPEXSCALEPART_ACTION ): 858*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize, 859*cdf0e10cSrcweir rSrcPtPixel, rSrcSizePixel, aBmpEx ) ); 860*cdf0e10cSrcweir break; 861*cdf0e10cSrcweir } 862*cdf0e10cSrcweir } 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir OUTDEV_INIT(); 865*cdf0e10cSrcweir 866*cdf0e10cSrcweir if( OUTDEV_PRINTER == meOutDevType ) 867*cdf0e10cSrcweir { 868*cdf0e10cSrcweir if( aBmpEx.IsAlpha() ) 869*cdf0e10cSrcweir { 870*cdf0e10cSrcweir // #107169# For true alpha bitmaps, no longer masking the 871*cdf0e10cSrcweir // bitmap, but perform a full alpha blend against a white 872*cdf0e10cSrcweir // background here. 873*cdf0e10cSrcweir Bitmap aBmp( aBmpEx.GetBitmap() ); 874*cdf0e10cSrcweir aBmp.Blend( aBmpEx.GetAlpha(), Color( COL_WHITE) ); 875*cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ); 876*cdf0e10cSrcweir } 877*cdf0e10cSrcweir else 878*cdf0e10cSrcweir { 879*cdf0e10cSrcweir Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() ); 880*cdf0e10cSrcweir aBmp.Replace( aMask, Color( COL_WHITE ) ); 881*cdf0e10cSrcweir ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel ); 882*cdf0e10cSrcweir } 883*cdf0e10cSrcweir return; 884*cdf0e10cSrcweir } 885*cdf0e10cSrcweir else if( aBmpEx.IsAlpha() ) 886*cdf0e10cSrcweir { 887*cdf0e10cSrcweir ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel ); 888*cdf0e10cSrcweir return; 889*cdf0e10cSrcweir } 890*cdf0e10cSrcweir 891*cdf0e10cSrcweir if( !( !aBmpEx ) ) 892*cdf0e10cSrcweir { 893*cdf0e10cSrcweir TwoRect aPosAry; 894*cdf0e10cSrcweir 895*cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X(); 896*cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y(); 897*cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width(); 898*cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height(); 899*cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 900*cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 901*cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 902*cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 903*cdf0e10cSrcweir 904*cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() ); 905*cdf0e10cSrcweir 906*cdf0e10cSrcweir if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 907*cdf0e10cSrcweir { 908*cdf0e10cSrcweir 909*cdf0e10cSrcweir if( nMirrFlags ) 910*cdf0e10cSrcweir aBmpEx.Mirror( nMirrFlags ); 911*cdf0e10cSrcweir 912*cdf0e10cSrcweir const ImpBitmap* pImpBmp = aBmpEx.ImplGetBitmapImpBitmap(); 913*cdf0e10cSrcweir const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap(); 914*cdf0e10cSrcweir 915*cdf0e10cSrcweir if ( pMaskBmp ) 916*cdf0e10cSrcweir { 917*cdf0e10cSrcweir // #4919452# reduce operation area to bounds of 918*cdf0e10cSrcweir // cliprect. since masked transparency involves 919*cdf0e10cSrcweir // creation of a large vdev and copying the screen 920*cdf0e10cSrcweir // content into that (slooow read from framebuffer), 921*cdf0e10cSrcweir // that should considerably increase performance for 922*cdf0e10cSrcweir // large bitmaps and small clippings. 923*cdf0e10cSrcweir 924*cdf0e10cSrcweir // Note that this optimisation is a workaround for a 925*cdf0e10cSrcweir // Writer peculiarity, namely, to decompose background 926*cdf0e10cSrcweir // graphics into myriads of disjunct, tiny 927*cdf0e10cSrcweir // rectangles. That otherwise kills us here, since for 928*cdf0e10cSrcweir // transparent output, SAL always prepares the whole 929*cdf0e10cSrcweir // bitmap, if aPosAry contains the whole bitmap (and 930*cdf0e10cSrcweir // it's _not_ to blame for that). 931*cdf0e10cSrcweir 932*cdf0e10cSrcweir // Note the call to ImplPixelToDevicePixel(), since 933*cdf0e10cSrcweir // aPosAry already contains the mnOutOff-offsets, they 934*cdf0e10cSrcweir // also have to be applied to the region 935*cdf0e10cSrcweir Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() ); 936*cdf0e10cSrcweir 937*cdf0e10cSrcweir // TODO: Also respect scaling (that's a bit tricky, 938*cdf0e10cSrcweir // since the source points have to move fractional 939*cdf0e10cSrcweir // amounts (which is not possible, thus has to be 940*cdf0e10cSrcweir // emulated by increases copy area) 941*cdf0e10cSrcweir // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth ); 942*cdf0e10cSrcweir // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight ); 943*cdf0e10cSrcweir 944*cdf0e10cSrcweir // for now, only identity scales allowed 945*cdf0e10cSrcweir if( !aClipRegionBounds.IsEmpty() && 946*cdf0e10cSrcweir aPosAry.mnDestWidth == aPosAry.mnSrcWidth && 947*cdf0e10cSrcweir aPosAry.mnDestHeight == aPosAry.mnSrcHeight ) 948*cdf0e10cSrcweir { 949*cdf0e10cSrcweir // now intersect dest rect with clip region 950*cdf0e10cSrcweir aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX, 951*cdf0e10cSrcweir aPosAry.mnDestY, 952*cdf0e10cSrcweir aPosAry.mnDestX + aPosAry.mnDestWidth - 1, 953*cdf0e10cSrcweir aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) ); 954*cdf0e10cSrcweir 955*cdf0e10cSrcweir // Note: I could theoretically optimize away the 956*cdf0e10cSrcweir // DrawBitmap below, if the region is empty 957*cdf0e10cSrcweir // here. Unfortunately, cannot rule out that 958*cdf0e10cSrcweir // somebody relies on the side effects. 959*cdf0e10cSrcweir if( !aClipRegionBounds.IsEmpty() ) 960*cdf0e10cSrcweir { 961*cdf0e10cSrcweir aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX; 962*cdf0e10cSrcweir aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY; 963*cdf0e10cSrcweir aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth(); 964*cdf0e10cSrcweir aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight(); 965*cdf0e10cSrcweir 966*cdf0e10cSrcweir aPosAry.mnDestX = aClipRegionBounds.Left(); 967*cdf0e10cSrcweir aPosAry.mnDestY = aClipRegionBounds.Top(); 968*cdf0e10cSrcweir aPosAry.mnDestWidth = aClipRegionBounds.GetWidth(); 969*cdf0e10cSrcweir aPosAry.mnDestHeight = aClipRegionBounds.GetHeight(); 970*cdf0e10cSrcweir } 971*cdf0e10cSrcweir } 972*cdf0e10cSrcweir 973*cdf0e10cSrcweir mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), 974*cdf0e10cSrcweir *pMaskBmp->ImplGetSalBitmap(), 975*cdf0e10cSrcweir this ); 976*cdf0e10cSrcweir 977*cdf0e10cSrcweir // #110958# Paint mask to alpha channel. Luckily, the 978*cdf0e10cSrcweir // black and white representation of the mask maps to 979*cdf0e10cSrcweir // the alpha channel 980*cdf0e10cSrcweir 981*cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 982*cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 983*cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 984*cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 985*cdf0e10cSrcweir // the transparency mask of itself 986*cdf0e10cSrcweir if( mpAlphaVDev ) 987*cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 988*cdf0e10cSrcweir rDestSize, 989*cdf0e10cSrcweir BitmapEx( aBmpEx.GetMask(), 990*cdf0e10cSrcweir aBmpEx.GetMask() ) ); 991*cdf0e10cSrcweir } 992*cdf0e10cSrcweir else 993*cdf0e10cSrcweir { 994*cdf0e10cSrcweir mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), this ); 995*cdf0e10cSrcweir 996*cdf0e10cSrcweir if( mpAlphaVDev ) 997*cdf0e10cSrcweir { 998*cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 999*cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 1000*cdf0e10cSrcweir } 1001*cdf0e10cSrcweir } 1002*cdf0e10cSrcweir } 1003*cdf0e10cSrcweir } 1004*cdf0e10cSrcweir } 1005*cdf0e10cSrcweir 1006*cdf0e10cSrcweir // ------------------------------------------------------------------ 1007*cdf0e10cSrcweir 1008*cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, 1009*cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor ) 1010*cdf0e10cSrcweir { 1011*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask()" ); 1012*cdf0e10cSrcweir 1013*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 1014*cdf0e10cSrcweir return; 1015*cdf0e10cSrcweir 1016*cdf0e10cSrcweir const Size aSizePix( rBitmap.GetSizePixel() ); 1017*cdf0e10cSrcweir ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION ); 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir if( mpAlphaVDev ) 1020*cdf0e10cSrcweir { 1021*cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) ); 1022*cdf0e10cSrcweir 1023*cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1024*cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1025*cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1026*cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1027*cdf0e10cSrcweir // the transparency mask of itself 1028*cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1029*cdf0e10cSrcweir PixelToLogic( aSizePix ), 1030*cdf0e10cSrcweir BitmapEx( rMask, rMask ) ); 1031*cdf0e10cSrcweir } 1032*cdf0e10cSrcweir } 1033*cdf0e10cSrcweir 1034*cdf0e10cSrcweir // ------------------------------------------------------------------ 1035*cdf0e10cSrcweir 1036*cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize, 1037*cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor ) 1038*cdf0e10cSrcweir { 1039*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask( Size )" ); 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 1042*cdf0e10cSrcweir return; 1043*cdf0e10cSrcweir 1044*cdf0e10cSrcweir ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION ); 1045*cdf0e10cSrcweir 1046*cdf0e10cSrcweir // TODO: Use mask here 1047*cdf0e10cSrcweir if( mpAlphaVDev ) 1048*cdf0e10cSrcweir { 1049*cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) ); 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1052*cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1053*cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1054*cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1055*cdf0e10cSrcweir // the transparency mask of itself 1056*cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1057*cdf0e10cSrcweir rDestSize, 1058*cdf0e10cSrcweir BitmapEx( rMask, rMask ) ); 1059*cdf0e10cSrcweir } 1060*cdf0e10cSrcweir } 1061*cdf0e10cSrcweir 1062*cdf0e10cSrcweir // ------------------------------------------------------------------ 1063*cdf0e10cSrcweir 1064*cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize, 1065*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 1066*cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor ) 1067*cdf0e10cSrcweir { 1068*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" ); 1069*cdf0e10cSrcweir 1070*cdf0e10cSrcweir if( ImplIsRecordLayout() ) 1071*cdf0e10cSrcweir return; 1072*cdf0e10cSrcweir 1073*cdf0e10cSrcweir ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION ); 1074*cdf0e10cSrcweir 1075*cdf0e10cSrcweir // TODO: Use mask here 1076*cdf0e10cSrcweir if( mpAlphaVDev ) 1077*cdf0e10cSrcweir { 1078*cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) ); 1079*cdf0e10cSrcweir 1080*cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1081*cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1082*cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1083*cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1084*cdf0e10cSrcweir // the transparency mask of itself 1085*cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1086*cdf0e10cSrcweir rDestSize, 1087*cdf0e10cSrcweir rSrcPtPixel, 1088*cdf0e10cSrcweir rSrcSizePixel, 1089*cdf0e10cSrcweir BitmapEx( rMask, rMask ) ); 1090*cdf0e10cSrcweir } 1091*cdf0e10cSrcweir } 1092*cdf0e10cSrcweir 1093*cdf0e10cSrcweir // ------------------------------------------------------------------ 1094*cdf0e10cSrcweir 1095*cdf0e10cSrcweir void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize, 1096*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 1097*cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor, 1098*cdf0e10cSrcweir const sal_uLong nAction ) 1099*cdf0e10cSrcweir { 1100*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1101*cdf0e10cSrcweir 1102*cdf0e10cSrcweir if( ROP_INVERT == meRasterOp ) 1103*cdf0e10cSrcweir { 1104*cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 1105*cdf0e10cSrcweir return; 1106*cdf0e10cSrcweir } 1107*cdf0e10cSrcweir 1108*cdf0e10cSrcweir if ( mpMetaFile ) 1109*cdf0e10cSrcweir { 1110*cdf0e10cSrcweir switch( nAction ) 1111*cdf0e10cSrcweir { 1112*cdf0e10cSrcweir case( META_MASK_ACTION ): 1113*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskAction( rDestPt, 1114*cdf0e10cSrcweir rBitmap, rMaskColor ) ); 1115*cdf0e10cSrcweir break; 1116*cdf0e10cSrcweir 1117*cdf0e10cSrcweir case( META_MASKSCALE_ACTION ): 1118*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt, 1119*cdf0e10cSrcweir rDestSize, rBitmap, rMaskColor ) ); 1120*cdf0e10cSrcweir break; 1121*cdf0e10cSrcweir 1122*cdf0e10cSrcweir case( META_MASKSCALEPART_ACTION ): 1123*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize, 1124*cdf0e10cSrcweir rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) ); 1125*cdf0e10cSrcweir break; 1126*cdf0e10cSrcweir } 1127*cdf0e10cSrcweir } 1128*cdf0e10cSrcweir 1129*cdf0e10cSrcweir OUTDEV_INIT(); 1130*cdf0e10cSrcweir 1131*cdf0e10cSrcweir if ( OUTDEV_PRINTER == meOutDevType ) 1132*cdf0e10cSrcweir { 1133*cdf0e10cSrcweir ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel ); 1134*cdf0e10cSrcweir return; 1135*cdf0e10cSrcweir } 1136*cdf0e10cSrcweir 1137*cdf0e10cSrcweir const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap(); 1138*cdf0e10cSrcweir if ( pImpBmp ) 1139*cdf0e10cSrcweir { 1140*cdf0e10cSrcweir TwoRect aPosAry; 1141*cdf0e10cSrcweir 1142*cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X(); 1143*cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y(); 1144*cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width(); 1145*cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height(); 1146*cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 1147*cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 1148*cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 1149*cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 1150*cdf0e10cSrcweir 1151*cdf0e10cSrcweir // spiegeln via Koordinaten wollen wir nicht 1152*cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() ); 1153*cdf0e10cSrcweir 1154*cdf0e10cSrcweir // check if output is necessary 1155*cdf0e10cSrcweir if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 1156*cdf0e10cSrcweir { 1157*cdf0e10cSrcweir 1158*cdf0e10cSrcweir if( nMirrFlags ) 1159*cdf0e10cSrcweir { 1160*cdf0e10cSrcweir Bitmap aTmp( rBitmap ); 1161*cdf0e10cSrcweir aTmp.Mirror( nMirrFlags ); 1162*cdf0e10cSrcweir mpGraphics->DrawMask( &aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(), 1163*cdf0e10cSrcweir ImplColorToSal( rMaskColor ) , this); 1164*cdf0e10cSrcweir } 1165*cdf0e10cSrcweir else 1166*cdf0e10cSrcweir mpGraphics->DrawMask( &aPosAry, *pImpBmp->ImplGetSalBitmap(), 1167*cdf0e10cSrcweir ImplColorToSal( rMaskColor ), this ); 1168*cdf0e10cSrcweir 1169*cdf0e10cSrcweir } 1170*cdf0e10cSrcweir } 1171*cdf0e10cSrcweir } 1172*cdf0e10cSrcweir 1173*cdf0e10cSrcweir // ------------------------------------------------------------------ 1174*cdf0e10cSrcweir 1175*cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle ) 1176*cdf0e10cSrcweir { 1177*cdf0e10cSrcweir DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" ); 1178*cdf0e10cSrcweir 1179*cdf0e10cSrcweir if( !rImage.mpImplData || ImplIsRecordLayout() ) 1180*cdf0e10cSrcweir return; 1181*cdf0e10cSrcweir 1182*cdf0e10cSrcweir switch( rImage.mpImplData->meType ) 1183*cdf0e10cSrcweir { 1184*cdf0e10cSrcweir case IMAGETYPE_BITMAP: 1185*cdf0e10cSrcweir DrawBitmap( rPos, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) ); 1186*cdf0e10cSrcweir break; 1187*cdf0e10cSrcweir 1188*cdf0e10cSrcweir case IMAGETYPE_IMAGE: 1189*cdf0e10cSrcweir { 1190*cdf0e10cSrcweir ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData ); 1191*cdf0e10cSrcweir 1192*cdf0e10cSrcweir if( !pData->mpImageBitmap ) 1193*cdf0e10cSrcweir { 1194*cdf0e10cSrcweir const Size aSize( pData->maBmpEx.GetSizePixel() ); 1195*cdf0e10cSrcweir 1196*cdf0e10cSrcweir pData->mpImageBitmap = new ImplImageBmp; 1197*cdf0e10cSrcweir pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 ); 1198*cdf0e10cSrcweir } 1199*cdf0e10cSrcweir 1200*cdf0e10cSrcweir pData->mpImageBitmap->Draw( 0, this, rPos, nStyle ); 1201*cdf0e10cSrcweir } 1202*cdf0e10cSrcweir break; 1203*cdf0e10cSrcweir 1204*cdf0e10cSrcweir default: 1205*cdf0e10cSrcweir break; 1206*cdf0e10cSrcweir } 1207*cdf0e10cSrcweir } 1208*cdf0e10cSrcweir 1209*cdf0e10cSrcweir // ------------------------------------------------------------------ 1210*cdf0e10cSrcweir 1211*cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Size& rSize, 1212*cdf0e10cSrcweir const Image& rImage, sal_uInt16 nStyle ) 1213*cdf0e10cSrcweir { 1214*cdf0e10cSrcweir DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" ); 1215*cdf0e10cSrcweir 1216*cdf0e10cSrcweir if( rImage.mpImplData && !ImplIsRecordLayout() ) 1217*cdf0e10cSrcweir { 1218*cdf0e10cSrcweir switch( rImage.mpImplData->meType ) 1219*cdf0e10cSrcweir { 1220*cdf0e10cSrcweir case IMAGETYPE_BITMAP: 1221*cdf0e10cSrcweir DrawBitmap( rPos, rSize, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) ); 1222*cdf0e10cSrcweir break; 1223*cdf0e10cSrcweir 1224*cdf0e10cSrcweir case IMAGETYPE_IMAGE: 1225*cdf0e10cSrcweir { 1226*cdf0e10cSrcweir ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData ); 1227*cdf0e10cSrcweir 1228*cdf0e10cSrcweir if ( !pData->mpImageBitmap ) 1229*cdf0e10cSrcweir { 1230*cdf0e10cSrcweir const Size aSize( pData->maBmpEx.GetSizePixel() ); 1231*cdf0e10cSrcweir 1232*cdf0e10cSrcweir pData->mpImageBitmap = new ImplImageBmp; 1233*cdf0e10cSrcweir pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 ); 1234*cdf0e10cSrcweir } 1235*cdf0e10cSrcweir 1236*cdf0e10cSrcweir pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize ); 1237*cdf0e10cSrcweir } 1238*cdf0e10cSrcweir break; 1239*cdf0e10cSrcweir 1240*cdf0e10cSrcweir default: 1241*cdf0e10cSrcweir break; 1242*cdf0e10cSrcweir } 1243*cdf0e10cSrcweir } 1244*cdf0e10cSrcweir } 1245*cdf0e10cSrcweir 1246*cdf0e10cSrcweir // ------------------------------------------------------------------ 1247*cdf0e10cSrcweir 1248*cdf0e10cSrcweir Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const 1249*cdf0e10cSrcweir { 1250*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1251*cdf0e10cSrcweir 1252*cdf0e10cSrcweir Bitmap aBmp; 1253*cdf0e10cSrcweir long nX = ImplLogicXToDevicePixel( rSrcPt.X() ); 1254*cdf0e10cSrcweir long nY = ImplLogicYToDevicePixel( rSrcPt.Y() ); 1255*cdf0e10cSrcweir long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() ); 1256*cdf0e10cSrcweir long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() ); 1257*cdf0e10cSrcweir 1258*cdf0e10cSrcweir if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() ) 1259*cdf0e10cSrcweir { 1260*cdf0e10cSrcweir if ( nWidth && nHeight ) 1261*cdf0e10cSrcweir { 1262*cdf0e10cSrcweir Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) ); 1263*cdf0e10cSrcweir sal_Bool bClipped = sal_False; 1264*cdf0e10cSrcweir 1265*cdf0e10cSrcweir // X-Koordinate ausserhalb des Bereichs? 1266*cdf0e10cSrcweir if ( nX < mnOutOffX ) 1267*cdf0e10cSrcweir { 1268*cdf0e10cSrcweir nWidth -= ( mnOutOffX - nX ); 1269*cdf0e10cSrcweir nX = mnOutOffX; 1270*cdf0e10cSrcweir bClipped = sal_True; 1271*cdf0e10cSrcweir } 1272*cdf0e10cSrcweir 1273*cdf0e10cSrcweir // Y-Koordinate ausserhalb des Bereichs? 1274*cdf0e10cSrcweir if ( nY < mnOutOffY ) 1275*cdf0e10cSrcweir { 1276*cdf0e10cSrcweir nHeight -= ( mnOutOffY - nY ); 1277*cdf0e10cSrcweir nY = mnOutOffY; 1278*cdf0e10cSrcweir bClipped = sal_True; 1279*cdf0e10cSrcweir } 1280*cdf0e10cSrcweir 1281*cdf0e10cSrcweir // Breite ausserhalb des Bereichs? 1282*cdf0e10cSrcweir if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) ) 1283*cdf0e10cSrcweir { 1284*cdf0e10cSrcweir nWidth = mnOutOffX + mnOutWidth - nX; 1285*cdf0e10cSrcweir bClipped = sal_True; 1286*cdf0e10cSrcweir } 1287*cdf0e10cSrcweir 1288*cdf0e10cSrcweir // Hoehe ausserhalb des Bereichs? 1289*cdf0e10cSrcweir if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) ) 1290*cdf0e10cSrcweir { 1291*cdf0e10cSrcweir nHeight = mnOutOffY + mnOutHeight - nY; 1292*cdf0e10cSrcweir bClipped = sal_True; 1293*cdf0e10cSrcweir } 1294*cdf0e10cSrcweir 1295*cdf0e10cSrcweir if ( bClipped ) 1296*cdf0e10cSrcweir { 1297*cdf0e10cSrcweir // Falls auf den sichtbaren Bereich geclipped wurde, 1298*cdf0e10cSrcweir // muessen wir eine Bitmap in der rchtigen Groesse 1299*cdf0e10cSrcweir // erzeugen, in die die geclippte Bitmap an die angepasste 1300*cdf0e10cSrcweir // Position kopiert wird 1301*cdf0e10cSrcweir VirtualDevice aVDev( *this ); 1302*cdf0e10cSrcweir 1303*cdf0e10cSrcweir if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) ) 1304*cdf0e10cSrcweir { 1305*cdf0e10cSrcweir if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() ) 1306*cdf0e10cSrcweir { 1307*cdf0e10cSrcweir TwoRect aPosAry; 1308*cdf0e10cSrcweir 1309*cdf0e10cSrcweir aPosAry.mnSrcX = nX; 1310*cdf0e10cSrcweir aPosAry.mnSrcY = nY; 1311*cdf0e10cSrcweir aPosAry.mnSrcWidth = nWidth; 1312*cdf0e10cSrcweir aPosAry.mnSrcHeight = nHeight; 1313*cdf0e10cSrcweir aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L; 1314*cdf0e10cSrcweir aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L; 1315*cdf0e10cSrcweir aPosAry.mnDestWidth = nWidth; 1316*cdf0e10cSrcweir aPosAry.mnDestHeight = nHeight; 1317*cdf0e10cSrcweir 1318*cdf0e10cSrcweir if ( (nWidth > 0) && (nHeight > 0) ) 1319*cdf0e10cSrcweir (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( &aPosAry, mpGraphics, this, this ); 1320*cdf0e10cSrcweir 1321*cdf0e10cSrcweir aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 1322*cdf0e10cSrcweir } 1323*cdf0e10cSrcweir else 1324*cdf0e10cSrcweir bClipped = sal_False; 1325*cdf0e10cSrcweir } 1326*cdf0e10cSrcweir else 1327*cdf0e10cSrcweir bClipped = sal_False; 1328*cdf0e10cSrcweir } 1329*cdf0e10cSrcweir 1330*cdf0e10cSrcweir if ( !bClipped ) 1331*cdf0e10cSrcweir { 1332*cdf0e10cSrcweir SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this ); 1333*cdf0e10cSrcweir 1334*cdf0e10cSrcweir if( pSalBmp ) 1335*cdf0e10cSrcweir { 1336*cdf0e10cSrcweir ImpBitmap* pImpBmp = new ImpBitmap; 1337*cdf0e10cSrcweir pImpBmp->ImplSetSalBitmap( pSalBmp ); 1338*cdf0e10cSrcweir aBmp.ImplSetImpBitmap( pImpBmp ); 1339*cdf0e10cSrcweir } 1340*cdf0e10cSrcweir } 1341*cdf0e10cSrcweir } 1342*cdf0e10cSrcweir } 1343*cdf0e10cSrcweir 1344*cdf0e10cSrcweir return aBmp; 1345*cdf0e10cSrcweir } 1346*cdf0e10cSrcweir 1347*cdf0e10cSrcweir // ------------------------------------------------------------------ 1348*cdf0e10cSrcweir 1349*cdf0e10cSrcweir BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const 1350*cdf0e10cSrcweir { 1351*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1352*cdf0e10cSrcweir 1353*cdf0e10cSrcweir // #110958# Extract alpha value from VDev, if any 1354*cdf0e10cSrcweir if( mpAlphaVDev ) 1355*cdf0e10cSrcweir { 1356*cdf0e10cSrcweir Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) ); 1357*cdf0e10cSrcweir 1358*cdf0e10cSrcweir // ensure 8 bit alpha 1359*cdf0e10cSrcweir if( aAlphaBitmap.GetBitCount() > 8 ) 1360*cdf0e10cSrcweir aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); 1361*cdf0e10cSrcweir 1362*cdf0e10cSrcweir return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) ); 1363*cdf0e10cSrcweir } 1364*cdf0e10cSrcweir else 1365*cdf0e10cSrcweir return GetBitmap( rSrcPt, rSize ); 1366*cdf0e10cSrcweir } 1367*cdf0e10cSrcweir 1368*cdf0e10cSrcweir // ------------------------------------------------------------------ 1369*cdf0e10cSrcweir 1370*cdf0e10cSrcweir void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize, 1371*cdf0e10cSrcweir Bitmap& rBitmap ) const 1372*cdf0e10cSrcweir { 1373*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1374*cdf0e10cSrcweir 1375*cdf0e10cSrcweir sal_Bool bOldMap = mbMap; 1376*cdf0e10cSrcweir ((OutputDevice*)this)->mbMap = sal_False; 1377*cdf0e10cSrcweir rBitmap = GetBitmap( rDestPt, rSize ); 1378*cdf0e10cSrcweir ((OutputDevice*)this)->mbMap = bOldMap; 1379*cdf0e10cSrcweir } 1380*cdf0e10cSrcweir 1381*cdf0e10cSrcweir // ------------------------------------------------------------------ 1382*cdf0e10cSrcweir 1383*cdf0e10cSrcweir Color OutputDevice::GetPixel( const Point& rPt ) const 1384*cdf0e10cSrcweir { 1385*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1386*cdf0e10cSrcweir 1387*cdf0e10cSrcweir Color aColor; 1388*cdf0e10cSrcweir 1389*cdf0e10cSrcweir if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() ) 1390*cdf0e10cSrcweir { 1391*cdf0e10cSrcweir if ( mbInitClipRegion ) 1392*cdf0e10cSrcweir ((OutputDevice*)this)->ImplInitClipRegion(); 1393*cdf0e10cSrcweir 1394*cdf0e10cSrcweir if ( !mbOutputClipped ) 1395*cdf0e10cSrcweir { 1396*cdf0e10cSrcweir const long nX = ImplLogicXToDevicePixel( rPt.X() ); 1397*cdf0e10cSrcweir const long nY = ImplLogicYToDevicePixel( rPt.Y() ); 1398*cdf0e10cSrcweir const SalColor aSalCol = mpGraphics->GetPixel( nX, nY, this ); 1399*cdf0e10cSrcweir aColor.SetRed( SALCOLOR_RED( aSalCol ) ); 1400*cdf0e10cSrcweir aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) ); 1401*cdf0e10cSrcweir aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) ); 1402*cdf0e10cSrcweir } 1403*cdf0e10cSrcweir } 1404*cdf0e10cSrcweir return aColor; 1405*cdf0e10cSrcweir } 1406*cdf0e10cSrcweir 1407*cdf0e10cSrcweir // ------------------------------------------------------------------ 1408*cdf0e10cSrcweir 1409*cdf0e10cSrcweir Color* OutputDevice::GetPixel( const Polygon& rPts ) const 1410*cdf0e10cSrcweir { 1411*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1412*cdf0e10cSrcweir 1413*cdf0e10cSrcweir Color* pColors = NULL; 1414*cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize(); 1415*cdf0e10cSrcweir 1416*cdf0e10cSrcweir if( nSize ) 1417*cdf0e10cSrcweir { 1418*cdf0e10cSrcweir if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() ) 1419*cdf0e10cSrcweir { 1420*cdf0e10cSrcweir if ( mbInitClipRegion ) 1421*cdf0e10cSrcweir ((OutputDevice*)this)->ImplInitClipRegion(); 1422*cdf0e10cSrcweir 1423*cdf0e10cSrcweir if ( !mbOutputClipped ) 1424*cdf0e10cSrcweir { 1425*cdf0e10cSrcweir pColors = new Color[ nSize ]; 1426*cdf0e10cSrcweir 1427*cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nSize; i++ ) 1428*cdf0e10cSrcweir { 1429*cdf0e10cSrcweir Color& rCol = pColors[ i ]; 1430*cdf0e10cSrcweir const Point& rPt = rPts[ i ]; 1431*cdf0e10cSrcweir const SalColor aSalCol( mpGraphics->GetPixel( ImplLogicXToDevicePixel( rPt.X() ), 1432*cdf0e10cSrcweir ImplLogicYToDevicePixel( rPt.Y() ) , this) ); 1433*cdf0e10cSrcweir 1434*cdf0e10cSrcweir rCol.SetRed( SALCOLOR_RED( aSalCol ) ); 1435*cdf0e10cSrcweir rCol.SetGreen( SALCOLOR_GREEN( aSalCol ) ); 1436*cdf0e10cSrcweir rCol.SetBlue( SALCOLOR_BLUE( aSalCol ) ); 1437*cdf0e10cSrcweir } 1438*cdf0e10cSrcweir } 1439*cdf0e10cSrcweir } 1440*cdf0e10cSrcweir } 1441*cdf0e10cSrcweir 1442*cdf0e10cSrcweir return pColors; 1443*cdf0e10cSrcweir } 1444*cdf0e10cSrcweir 1445*cdf0e10cSrcweir // ----------------------------------------------------------------------- 1446*cdf0e10cSrcweir 1447*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt ) 1448*cdf0e10cSrcweir { 1449*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" ); 1450*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1451*cdf0e10cSrcweir 1452*cdf0e10cSrcweir if ( mpMetaFile ) 1453*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPointAction( rPt ) ); 1454*cdf0e10cSrcweir 1455*cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() ) 1456*cdf0e10cSrcweir return; 1457*cdf0e10cSrcweir 1458*cdf0e10cSrcweir Point aPt = ImplLogicToDevicePixel( rPt ); 1459*cdf0e10cSrcweir 1460*cdf0e10cSrcweir // we need a graphics 1461*cdf0e10cSrcweir if ( !mpGraphics ) 1462*cdf0e10cSrcweir { 1463*cdf0e10cSrcweir if ( !ImplGetGraphics() ) 1464*cdf0e10cSrcweir return; 1465*cdf0e10cSrcweir } 1466*cdf0e10cSrcweir 1467*cdf0e10cSrcweir if ( mbInitClipRegion ) 1468*cdf0e10cSrcweir ImplInitClipRegion(); 1469*cdf0e10cSrcweir if ( mbOutputClipped ) 1470*cdf0e10cSrcweir return; 1471*cdf0e10cSrcweir 1472*cdf0e10cSrcweir if ( mbInitLineColor ) 1473*cdf0e10cSrcweir ImplInitLineColor(); 1474*cdf0e10cSrcweir 1475*cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), this ); 1476*cdf0e10cSrcweir 1477*cdf0e10cSrcweir if( mpAlphaVDev ) 1478*cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPt ); 1479*cdf0e10cSrcweir } 1480*cdf0e10cSrcweir 1481*cdf0e10cSrcweir // ----------------------------------------------------------------------- 1482*cdf0e10cSrcweir 1483*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor ) 1484*cdf0e10cSrcweir { 1485*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" ); 1486*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1487*cdf0e10cSrcweir 1488*cdf0e10cSrcweir Color aColor( rColor ); 1489*cdf0e10cSrcweir 1490*cdf0e10cSrcweir if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE | 1491*cdf0e10cSrcweir DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE | 1492*cdf0e10cSrcweir DRAWMODE_SETTINGSLINE ) ) 1493*cdf0e10cSrcweir { 1494*cdf0e10cSrcweir if( !ImplIsColorTransparent( aColor ) ) 1495*cdf0e10cSrcweir { 1496*cdf0e10cSrcweir if( mnDrawMode & DRAWMODE_BLACKLINE ) 1497*cdf0e10cSrcweir { 1498*cdf0e10cSrcweir aColor = Color( COL_BLACK ); 1499*cdf0e10cSrcweir } 1500*cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_WHITELINE ) 1501*cdf0e10cSrcweir { 1502*cdf0e10cSrcweir aColor = Color( COL_WHITE ); 1503*cdf0e10cSrcweir } 1504*cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_GRAYLINE ) 1505*cdf0e10cSrcweir { 1506*cdf0e10cSrcweir const sal_uInt8 cLum = aColor.GetLuminance(); 1507*cdf0e10cSrcweir aColor = Color( cLum, cLum, cLum ); 1508*cdf0e10cSrcweir } 1509*cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_SETTINGSLINE ) 1510*cdf0e10cSrcweir { 1511*cdf0e10cSrcweir aColor = GetSettings().GetStyleSettings().GetFontColor(); 1512*cdf0e10cSrcweir } 1513*cdf0e10cSrcweir 1514*cdf0e10cSrcweir if( mnDrawMode & DRAWMODE_GHOSTEDLINE ) 1515*cdf0e10cSrcweir { 1516*cdf0e10cSrcweir aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80, 1517*cdf0e10cSrcweir ( aColor.GetGreen() >> 1 ) | 0x80, 1518*cdf0e10cSrcweir ( aColor.GetBlue() >> 1 ) | 0x80 ); 1519*cdf0e10cSrcweir } 1520*cdf0e10cSrcweir } 1521*cdf0e10cSrcweir } 1522*cdf0e10cSrcweir 1523*cdf0e10cSrcweir if ( mpMetaFile ) 1524*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) ); 1525*cdf0e10cSrcweir 1526*cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) || ImplIsRecordLayout() ) 1527*cdf0e10cSrcweir return; 1528*cdf0e10cSrcweir 1529*cdf0e10cSrcweir Point aPt = ImplLogicToDevicePixel( rPt ); 1530*cdf0e10cSrcweir 1531*cdf0e10cSrcweir // we need a graphics 1532*cdf0e10cSrcweir if ( !mpGraphics ) 1533*cdf0e10cSrcweir { 1534*cdf0e10cSrcweir if ( !ImplGetGraphics() ) 1535*cdf0e10cSrcweir return; 1536*cdf0e10cSrcweir } 1537*cdf0e10cSrcweir 1538*cdf0e10cSrcweir if ( mbInitClipRegion ) 1539*cdf0e10cSrcweir ImplInitClipRegion(); 1540*cdf0e10cSrcweir if ( mbOutputClipped ) 1541*cdf0e10cSrcweir return; 1542*cdf0e10cSrcweir 1543*cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ), this ); 1544*cdf0e10cSrcweir 1545*cdf0e10cSrcweir if( mpAlphaVDev ) 1546*cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPt ); 1547*cdf0e10cSrcweir } 1548*cdf0e10cSrcweir 1549*cdf0e10cSrcweir // ----------------------------------------------------------------------- 1550*cdf0e10cSrcweir 1551*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors ) 1552*cdf0e10cSrcweir { 1553*cdf0e10cSrcweir if ( !pColors ) 1554*cdf0e10cSrcweir DrawPixel( rPts, GetLineColor() ); 1555*cdf0e10cSrcweir else 1556*cdf0e10cSrcweir { 1557*cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" ); 1558*cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1559*cdf0e10cSrcweir DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" ); 1560*cdf0e10cSrcweir 1561*cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize(); 1562*cdf0e10cSrcweir 1563*cdf0e10cSrcweir if ( nSize ) 1564*cdf0e10cSrcweir { 1565*cdf0e10cSrcweir if ( mpMetaFile ) 1566*cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSize; i++ ) 1567*cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) ); 1568*cdf0e10cSrcweir 1569*cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1570*cdf0e10cSrcweir return; 1571*cdf0e10cSrcweir 1572*cdf0e10cSrcweir // we need a graphics 1573*cdf0e10cSrcweir if ( mpGraphics || ImplGetGraphics() ) 1574*cdf0e10cSrcweir { 1575*cdf0e10cSrcweir if ( mbInitClipRegion ) 1576*cdf0e10cSrcweir ImplInitClipRegion(); 1577*cdf0e10cSrcweir 1578*cdf0e10cSrcweir if ( mbOutputClipped ) 1579*cdf0e10cSrcweir return; 1580*cdf0e10cSrcweir 1581*cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSize; i++ ) 1582*cdf0e10cSrcweir { 1583*cdf0e10cSrcweir const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) ); 1584*cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ), this ); 1585*cdf0e10cSrcweir } 1586*cdf0e10cSrcweir } 1587*cdf0e10cSrcweir } 1588*cdf0e10cSrcweir } 1589*cdf0e10cSrcweir 1590*cdf0e10cSrcweir if( mpAlphaVDev ) 1591*cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPts, pColors ); 1592*cdf0e10cSrcweir } 1593*cdf0e10cSrcweir 1594*cdf0e10cSrcweir // ----------------------------------------------------------------------- 1595*cdf0e10cSrcweir 1596*cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor ) 1597*cdf0e10cSrcweir { 1598*cdf0e10cSrcweir if( rColor != COL_TRANSPARENT && ! ImplIsRecordLayout() ) 1599*cdf0e10cSrcweir { 1600*cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize(); 1601*cdf0e10cSrcweir Color* pColArray = new Color[ nSize ]; 1602*cdf0e10cSrcweir 1603*cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nSize; i++ ) 1604*cdf0e10cSrcweir pColArray[ i ] = rColor; 1605*cdf0e10cSrcweir 1606*cdf0e10cSrcweir DrawPixel( rPts, pColArray ); 1607*cdf0e10cSrcweir delete[] pColArray; 1608*cdf0e10cSrcweir } 1609*cdf0e10cSrcweir 1610*cdf0e10cSrcweir if( mpAlphaVDev ) 1611*cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPts, rColor ); 1612*cdf0e10cSrcweir } 1613*cdf0e10cSrcweir 1614*cdf0e10cSrcweir // ------------------------------------------------------------------------ 1615*cdf0e10cSrcweir 1616*cdf0e10cSrcweir namespace 1617*cdf0e10cSrcweir { 1618*cdf0e10cSrcweir sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceOpaq, const sal_uInt8 nDestColor ) 1619*cdf0e10cSrcweir { 1620*cdf0e10cSrcweir int c = ( (int)nDestColor * ( 255 - nSourceOpaq ) ) 1621*cdf0e10cSrcweir + (int)nSourceOpaq * (int)nSourceColor; 1622*cdf0e10cSrcweir return sal_uInt8( c / 255 ); 1623*cdf0e10cSrcweir } 1624*cdf0e10cSrcweir } 1625*cdf0e10cSrcweir 1626*cdf0e10cSrcweir // ------------------------------------------------------------------------ 1627*cdf0e10cSrcweir 1628*cdf0e10cSrcweir Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, 1629*cdf0e10cSrcweir BitmapReadAccess* pP, 1630*cdf0e10cSrcweir BitmapReadAccess* pA, 1631*cdf0e10cSrcweir const Rectangle& aDstRect, 1632*cdf0e10cSrcweir const sal_Int32 nOffY, 1633*cdf0e10cSrcweir const sal_Int32 nDstHeight, 1634*cdf0e10cSrcweir const sal_Int32 nOffX, 1635*cdf0e10cSrcweir const sal_Int32 nDstWidth, 1636*cdf0e10cSrcweir const long* pMapX, 1637*cdf0e10cSrcweir const long* pMapY ) 1638*cdf0e10cSrcweir { 1639*cdf0e10cSrcweir BitmapColor aDstCol,aSrcCol; 1640*cdf0e10cSrcweir Bitmap res; 1641*cdf0e10cSrcweir int nX, nOutX, nY, nOutY; 1642*cdf0e10cSrcweir 1643*cdf0e10cSrcweir OSL_ENSURE(mpAlphaVDev, 1644*cdf0e10cSrcweir "ImplBlendWithAlpha(): call me only with valid alpha VDev!" ); 1645*cdf0e10cSrcweir 1646*cdf0e10cSrcweir sal_Bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() ); 1647*cdf0e10cSrcweir mpAlphaVDev->EnableMapMode(sal_False); 1648*cdf0e10cSrcweir 1649*cdf0e10cSrcweir Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) ); 1650*cdf0e10cSrcweir BitmapWriteAccess* pAlphaW = aAlphaBitmap.AcquireWriteAccess(); 1651*cdf0e10cSrcweir 1652*cdf0e10cSrcweir if( GetBitCount() <= 8 ) 1653*cdf0e10cSrcweir { 1654*cdf0e10cSrcweir Bitmap aDither( aBmp.GetSizePixel(), 8 ); 1655*cdf0e10cSrcweir BitmapColor aIndex( 0 ); 1656*cdf0e10cSrcweir BitmapReadAccess* pB = aBmp.AcquireReadAccess(); 1657*cdf0e10cSrcweir BitmapWriteAccess* pW = aDither.AcquireWriteAccess(); 1658*cdf0e10cSrcweir 1659*cdf0e10cSrcweir if( pB && pP && pA && pW && pAlphaW ) 1660*cdf0e10cSrcweir { 1661*cdf0e10cSrcweir for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) 1662*cdf0e10cSrcweir { 1663*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1664*cdf0e10cSrcweir const long nModY = ( nOutY & 0x0FL ) << 4L; 1665*cdf0e10cSrcweir 1666*cdf0e10cSrcweir for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) 1667*cdf0e10cSrcweir { 1668*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1669*cdf0e10cSrcweir const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ]; 1670*cdf0e10cSrcweir 1671*cdf0e10cSrcweir aSrcCol = pP->GetColor( nMapY, nMapX ); 1672*cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX ); 1673*cdf0e10cSrcweir const sal_uInt8 nSrcOpaq = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); 1674*cdf0e10cSrcweir const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); 1675*cdf0e10cSrcweir 1676*cdf0e10cSrcweir aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) ); 1677*cdf0e10cSrcweir aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) ); 1678*cdf0e10cSrcweir aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) ); 1679*cdf0e10cSrcweir 1680*cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] + 1681*cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] + 1682*cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) ); 1683*cdf0e10cSrcweir pW->SetPixel( nY, nX, aIndex ); 1684*cdf0e10cSrcweir 1685*cdf0e10cSrcweir // Have to perform the compositing 'algebra' in 1686*cdf0e10cSrcweir // the inverse alpha space (with 255 meaning 1687*cdf0e10cSrcweir // opaque), otherwise, transitivity is not 1688*cdf0e10cSrcweir // achieved. 1689*cdf0e10cSrcweir const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq ); 1690*cdf0e10cSrcweir 1691*cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] + 1692*cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] + 1693*cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] ) ); 1694*cdf0e10cSrcweir pAlphaW->SetPixel( nY, nX, aIndex ); 1695*cdf0e10cSrcweir } 1696*cdf0e10cSrcweir } 1697*cdf0e10cSrcweir } 1698*cdf0e10cSrcweir 1699*cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 1700*cdf0e10cSrcweir aDither.ReleaseAccess( pW ); 1701*cdf0e10cSrcweir res = aDither; 1702*cdf0e10cSrcweir } 1703*cdf0e10cSrcweir else 1704*cdf0e10cSrcweir { 1705*cdf0e10cSrcweir BitmapWriteAccess* pB = aBmp.AcquireWriteAccess(); 1706*cdf0e10cSrcweir if( pP && pA && pB ) 1707*cdf0e10cSrcweir { 1708*cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 1709*cdf0e10cSrcweir { 1710*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1711*cdf0e10cSrcweir 1712*cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 1713*cdf0e10cSrcweir { 1714*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1715*cdf0e10cSrcweir 1716*cdf0e10cSrcweir aSrcCol = pP->GetColor( nMapY, nMapX ); 1717*cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX ); 1718*cdf0e10cSrcweir const sal_uInt8 nSrcOpaq = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex(); 1719*cdf0e10cSrcweir const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex(); 1720*cdf0e10cSrcweir 1721*cdf0e10cSrcweir aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) ); 1722*cdf0e10cSrcweir aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) ); 1723*cdf0e10cSrcweir aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) ); 1724*cdf0e10cSrcweir 1725*cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol ); 1726*cdf0e10cSrcweir 1727*cdf0e10cSrcweir // Have to perform the compositing 'algebra' in 1728*cdf0e10cSrcweir // the inverse alpha space (with 255 meaning 1729*cdf0e10cSrcweir // opaque), otherwise, transitivity is not 1730*cdf0e10cSrcweir // achieved. 1731*cdf0e10cSrcweir const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq ); 1732*cdf0e10cSrcweir 1733*cdf0e10cSrcweir pAlphaW->SetPixel( nY, nX, Color(nSrcAlpha, nSrcAlpha, nSrcAlpha) ); 1734*cdf0e10cSrcweir } 1735*cdf0e10cSrcweir } 1736*cdf0e10cSrcweir } 1737*cdf0e10cSrcweir 1738*cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 1739*cdf0e10cSrcweir res = aBmp; 1740*cdf0e10cSrcweir } 1741*cdf0e10cSrcweir 1742*cdf0e10cSrcweir aAlphaBitmap.ReleaseAccess( pAlphaW ); 1743*cdf0e10cSrcweir mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap ); 1744*cdf0e10cSrcweir mpAlphaVDev->EnableMapMode( bOldMapMode ); 1745*cdf0e10cSrcweir 1746*cdf0e10cSrcweir return res; 1747*cdf0e10cSrcweir } 1748*cdf0e10cSrcweir 1749*cdf0e10cSrcweir // ------------------------------------------------------------------------ 1750*cdf0e10cSrcweir 1751*cdf0e10cSrcweir Bitmap OutputDevice::ImplBlend( Bitmap aBmp, 1752*cdf0e10cSrcweir BitmapReadAccess* pP, 1753*cdf0e10cSrcweir BitmapReadAccess* pA, 1754*cdf0e10cSrcweir const sal_Int32 nOffY, 1755*cdf0e10cSrcweir const sal_Int32 nDstHeight, 1756*cdf0e10cSrcweir const sal_Int32 nOffX, 1757*cdf0e10cSrcweir const sal_Int32 nDstWidth, 1758*cdf0e10cSrcweir const Rectangle& aBmpRect, 1759*cdf0e10cSrcweir const Size& aOutSz, 1760*cdf0e10cSrcweir const bool bHMirr, 1761*cdf0e10cSrcweir const bool bVMirr, 1762*cdf0e10cSrcweir const long* pMapX, 1763*cdf0e10cSrcweir const long* pMapY ) 1764*cdf0e10cSrcweir { 1765*cdf0e10cSrcweir BitmapColor aDstCol; 1766*cdf0e10cSrcweir Bitmap res; 1767*cdf0e10cSrcweir int nX, nOutX, nY, nOutY; 1768*cdf0e10cSrcweir 1769*cdf0e10cSrcweir if( GetBitCount() <= 8 ) 1770*cdf0e10cSrcweir { 1771*cdf0e10cSrcweir Bitmap aDither( aBmp.GetSizePixel(), 8 ); 1772*cdf0e10cSrcweir BitmapColor aIndex( 0 ); 1773*cdf0e10cSrcweir BitmapReadAccess* pB = aBmp.AcquireReadAccess(); 1774*cdf0e10cSrcweir BitmapWriteAccess* pW = aDither.AcquireWriteAccess(); 1775*cdf0e10cSrcweir 1776*cdf0e10cSrcweir if( pB && pP && pA && pW ) 1777*cdf0e10cSrcweir { 1778*cdf0e10cSrcweir for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) 1779*cdf0e10cSrcweir { 1780*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1781*cdf0e10cSrcweir const long nModY = ( nOutY & 0x0FL ) << 4L; 1782*cdf0e10cSrcweir 1783*cdf0e10cSrcweir for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) 1784*cdf0e10cSrcweir { 1785*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1786*cdf0e10cSrcweir const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ]; 1787*cdf0e10cSrcweir 1788*cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX ); 1789*cdf0e10cSrcweir aDstCol.Merge( pP->GetColor( nMapY, nMapX ), (sal_uInt8) pA->GetPixel( nMapY, nMapX ) ); 1790*cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] + 1791*cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] + 1792*cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) ); 1793*cdf0e10cSrcweir pW->SetPixel( nY, nX, aIndex ); 1794*cdf0e10cSrcweir } 1795*cdf0e10cSrcweir } 1796*cdf0e10cSrcweir } 1797*cdf0e10cSrcweir 1798*cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 1799*cdf0e10cSrcweir aDither.ReleaseAccess( pW ); 1800*cdf0e10cSrcweir res = aDither; 1801*cdf0e10cSrcweir } 1802*cdf0e10cSrcweir else 1803*cdf0e10cSrcweir { 1804*cdf0e10cSrcweir BitmapWriteAccess* pB = aBmp.AcquireWriteAccess(); 1805*cdf0e10cSrcweir 1806*cdf0e10cSrcweir bool bFastBlend = false; 1807*cdf0e10cSrcweir if( pP && pA && pB ) 1808*cdf0e10cSrcweir { 1809*cdf0e10cSrcweir SalTwoRect aTR; 1810*cdf0e10cSrcweir aTR.mnSrcX = aBmpRect.Left(); 1811*cdf0e10cSrcweir aTR.mnSrcY = aBmpRect.Top(); 1812*cdf0e10cSrcweir aTR.mnSrcWidth = aBmpRect.GetWidth(); 1813*cdf0e10cSrcweir aTR.mnSrcHeight = aBmpRect.GetHeight(); 1814*cdf0e10cSrcweir aTR.mnDestX = nOffX; 1815*cdf0e10cSrcweir aTR.mnDestY = nOffY; 1816*cdf0e10cSrcweir aTR.mnDestWidth = aOutSz.Width(); 1817*cdf0e10cSrcweir aTR.mnDestHeight= aOutSz.Height(); 1818*cdf0e10cSrcweir 1819*cdf0e10cSrcweir if( !bHMirr || !bVMirr ) 1820*cdf0e10cSrcweir bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR ); 1821*cdf0e10cSrcweir } 1822*cdf0e10cSrcweir 1823*cdf0e10cSrcweir if( pP && pA && pB && !bFastBlend ) 1824*cdf0e10cSrcweir { 1825*cdf0e10cSrcweir switch( pP->GetScanlineFormat() ) 1826*cdf0e10cSrcweir { 1827*cdf0e10cSrcweir case( BMP_FORMAT_8BIT_PAL ): 1828*cdf0e10cSrcweir { 1829*cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 1830*cdf0e10cSrcweir { 1831*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1832*cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY ); 1833*cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 1834*cdf0e10cSrcweir 1835*cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 1836*cdf0e10cSrcweir { 1837*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1838*cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 1839*cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ), 1840*cdf0e10cSrcweir pAScan[ nMapX ] ) ); 1841*cdf0e10cSrcweir } 1842*cdf0e10cSrcweir } 1843*cdf0e10cSrcweir } 1844*cdf0e10cSrcweir break; 1845*cdf0e10cSrcweir 1846*cdf0e10cSrcweir case( BMP_FORMAT_24BIT_TC_BGR ): 1847*cdf0e10cSrcweir { 1848*cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 1849*cdf0e10cSrcweir { 1850*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1851*cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY ); 1852*cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 1853*cdf0e10cSrcweir 1854*cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 1855*cdf0e10cSrcweir { 1856*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1857*cdf0e10cSrcweir Scanline pTmp = pPScan + nMapX * 3; 1858*cdf0e10cSrcweir 1859*cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 1860*cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ], 1861*cdf0e10cSrcweir pAScan[ nMapX ] ) ); 1862*cdf0e10cSrcweir } 1863*cdf0e10cSrcweir } 1864*cdf0e10cSrcweir } 1865*cdf0e10cSrcweir break; 1866*cdf0e10cSrcweir 1867*cdf0e10cSrcweir case( BMP_FORMAT_24BIT_TC_RGB ): 1868*cdf0e10cSrcweir { 1869*cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 1870*cdf0e10cSrcweir { 1871*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1872*cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY ); 1873*cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 1874*cdf0e10cSrcweir 1875*cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 1876*cdf0e10cSrcweir { 1877*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1878*cdf0e10cSrcweir Scanline pTmp = pPScan + nMapX * 3; 1879*cdf0e10cSrcweir 1880*cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 1881*cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ], 1882*cdf0e10cSrcweir pAScan[ nMapX ] ) ); 1883*cdf0e10cSrcweir } 1884*cdf0e10cSrcweir } 1885*cdf0e10cSrcweir } 1886*cdf0e10cSrcweir break; 1887*cdf0e10cSrcweir 1888*cdf0e10cSrcweir default: 1889*cdf0e10cSrcweir { 1890*cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 1891*cdf0e10cSrcweir { 1892*cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1893*cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 1894*cdf0e10cSrcweir 1895*cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 1896*cdf0e10cSrcweir { 1897*cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1898*cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 1899*cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ), 1900*cdf0e10cSrcweir pAScan[ nMapX ] ) ); 1901*cdf0e10cSrcweir } 1902*cdf0e10cSrcweir } 1903*cdf0e10cSrcweir } 1904*cdf0e10cSrcweir break; 1905*cdf0e10cSrcweir } 1906*cdf0e10cSrcweir } 1907*cdf0e10cSrcweir 1908*cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 1909*cdf0e10cSrcweir res = aBmp; 1910*cdf0e10cSrcweir } 1911*cdf0e10cSrcweir 1912*cdf0e10cSrcweir return res; 1913*cdf0e10cSrcweir } 1914*cdf0e10cSrcweir 1915*cdf0e10cSrcweir // ------------------------------------------------------------------------ 1916*cdf0e10cSrcweir 1917*cdf0e10cSrcweir void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha, 1918*cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize, 1919*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel ) 1920*cdf0e10cSrcweir { 1921*cdf0e10cSrcweir const Point aNullPt; 1922*cdf0e10cSrcweir Point aOutPt( LogicToPixel( rDestPt ) ); 1923*cdf0e10cSrcweir Size aOutSz( LogicToPixel( rDestSize ) ); 1924*cdf0e10cSrcweir Rectangle aDstRect( aNullPt, GetOutputSizePixel() ); 1925*cdf0e10cSrcweir const sal_Bool bHMirr = aOutSz.Width() < 0, bVMirr = aOutSz.Height() < 0; 1926*cdf0e10cSrcweir 1927*cdf0e10cSrcweir if( OUTDEV_WINDOW == meOutDevType ) 1928*cdf0e10cSrcweir { 1929*cdf0e10cSrcweir const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 1930*cdf0e10cSrcweir 1931*cdf0e10cSrcweir if( !aPaintRgn.IsNull() ) 1932*cdf0e10cSrcweir aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) ); 1933*cdf0e10cSrcweir } 1934*cdf0e10cSrcweir 1935*cdf0e10cSrcweir if( bHMirr ) 1936*cdf0e10cSrcweir { 1937*cdf0e10cSrcweir aOutSz.Width() = -aOutSz.Width(); 1938*cdf0e10cSrcweir aOutPt.X() -= ( aOutSz.Width() - 1L ); 1939*cdf0e10cSrcweir } 1940*cdf0e10cSrcweir 1941*cdf0e10cSrcweir if( bVMirr ) 1942*cdf0e10cSrcweir { 1943*cdf0e10cSrcweir aOutSz.Height() = -aOutSz.Height(); 1944*cdf0e10cSrcweir aOutPt.Y() -= ( aOutSz.Height() - 1L ); 1945*cdf0e10cSrcweir } 1946*cdf0e10cSrcweir 1947*cdf0e10cSrcweir if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() ) 1948*cdf0e10cSrcweir { 1949*cdf0e10cSrcweir bool bNativeAlpha = false; 1950*cdf0e10cSrcweir static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA"); 1951*cdf0e10cSrcweir // #i83087# Naturally, system alpha blending cannot work with 1952*cdf0e10cSrcweir // separate alpha VDev 1953*cdf0e10cSrcweir if( !mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr ) 1954*cdf0e10cSrcweir { 1955*cdf0e10cSrcweir Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY ); 1956*cdf0e10cSrcweir SalTwoRect aTR = { 1957*cdf0e10cSrcweir rSrcPtPixel.X(), rSrcPtPixel.Y(), 1958*cdf0e10cSrcweir rSrcSizePixel.Width(), rSrcSizePixel.Height(), 1959*cdf0e10cSrcweir aRelPt.X(), aRelPt.Y(), 1960*cdf0e10cSrcweir aOutSz.Width(), aOutSz.Height() 1961*cdf0e10cSrcweir }; 1962*cdf0e10cSrcweir SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap(); 1963*cdf0e10cSrcweir SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap(); 1964*cdf0e10cSrcweir bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this ); 1965*cdf0e10cSrcweir } 1966*cdf0e10cSrcweir 1967*cdf0e10cSrcweir VirtualDevice* pOldVDev = mpAlphaVDev; 1968*cdf0e10cSrcweir 1969*cdf0e10cSrcweir Rectangle aBmpRect( aNullPt, rBmp.GetSizePixel() ); 1970*cdf0e10cSrcweir if( !bNativeAlpha 1971*cdf0e10cSrcweir && !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() ) 1972*cdf0e10cSrcweir { 1973*cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; mpMetaFile = NULL; 1974*cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; mbMap = sal_False; 1975*cdf0e10cSrcweir Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) ); 1976*cdf0e10cSrcweir 1977*cdf0e10cSrcweir // #109044# The generated bitmap need not necessarily be 1978*cdf0e10cSrcweir // of aDstRect dimensions, it's internally clipped to 1979*cdf0e10cSrcweir // window bounds. Thus, we correct the dest size here, 1980*cdf0e10cSrcweir // since we later use it (in nDstWidth/Height) for pixel 1981*cdf0e10cSrcweir // access) 1982*cdf0e10cSrcweir // #i38887# reading from screen may sometimes fail 1983*cdf0e10cSrcweir if( aBmp.ImplGetImpBitmap() ) 1984*cdf0e10cSrcweir aDstRect.SetSize( aBmp.GetSizePixel() ); 1985*cdf0e10cSrcweir 1986*cdf0e10cSrcweir BitmapColor aDstCol; 1987*cdf0e10cSrcweir const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight(); 1988*cdf0e10cSrcweir const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight(); 1989*cdf0e10cSrcweir const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height(); 1990*cdf0e10cSrcweir // calculate offset in original bitmap 1991*cdf0e10cSrcweir // in RTL case this is a little more complicated since the contents of the 1992*cdf0e10cSrcweir // bitmap is not mirrored (it never is), however the paint region and bmp region 1993*cdf0e10cSrcweir // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these 1994*cdf0e10cSrcweir // is content wise somewhere else and needs to take mirroring into account 1995*cdf0e10cSrcweir const long nOffX = IsRTLEnabled() 1996*cdf0e10cSrcweir ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X()) 1997*cdf0e10cSrcweir : aDstRect.Left() - aOutPt.X(), 1998*cdf0e10cSrcweir nOffY = aDstRect.Top() - aOutPt.Y(); 1999*cdf0e10cSrcweir long nX, nOutX, nY, nOutY; 2000*cdf0e10cSrcweir long nMirrOffX = 0; 2001*cdf0e10cSrcweir long nMirrOffY = 0; 2002*cdf0e10cSrcweir long* pMapX = new long[ nDstWidth ]; 2003*cdf0e10cSrcweir long* pMapY = new long[ nDstHeight ]; 2004*cdf0e10cSrcweir 2005*cdf0e10cSrcweir // create horizontal mapping table 2006*cdf0e10cSrcweir if( bHMirr ) 2007*cdf0e10cSrcweir nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1; 2008*cdf0e10cSrcweir 2009*cdf0e10cSrcweir for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) 2010*cdf0e10cSrcweir { 2011*cdf0e10cSrcweir pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth; 2012*cdf0e10cSrcweir if( bHMirr ) 2013*cdf0e10cSrcweir pMapX[ nX ] = nMirrOffX - pMapX[ nX ]; 2014*cdf0e10cSrcweir } 2015*cdf0e10cSrcweir 2016*cdf0e10cSrcweir // create vertical mapping table 2017*cdf0e10cSrcweir if( bVMirr ) 2018*cdf0e10cSrcweir nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1; 2019*cdf0e10cSrcweir 2020*cdf0e10cSrcweir for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) 2021*cdf0e10cSrcweir { 2022*cdf0e10cSrcweir pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight; 2023*cdf0e10cSrcweir 2024*cdf0e10cSrcweir if( bVMirr ) 2025*cdf0e10cSrcweir pMapY[ nY ] = nMirrOffY - pMapY[ nY ]; 2026*cdf0e10cSrcweir } 2027*cdf0e10cSrcweir 2028*cdf0e10cSrcweir BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess(); 2029*cdf0e10cSrcweir BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); 2030*cdf0e10cSrcweir 2031*cdf0e10cSrcweir DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || 2032*cdf0e10cSrcweir pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK, 2033*cdf0e10cSrcweir "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" ); 2034*cdf0e10cSrcweir 2035*cdf0e10cSrcweir // #i38887# reading from screen may sometimes fail 2036*cdf0e10cSrcweir if( aBmp.ImplGetImpBitmap() ) 2037*cdf0e10cSrcweir { 2038*cdf0e10cSrcweir Bitmap aTmp; 2039*cdf0e10cSrcweir 2040*cdf0e10cSrcweir if( mpAlphaVDev ) 2041*cdf0e10cSrcweir { 2042*cdf0e10cSrcweir aTmp = ImplBlendWithAlpha( 2043*cdf0e10cSrcweir aBmp,pP,pA, 2044*cdf0e10cSrcweir aDstRect, 2045*cdf0e10cSrcweir nOffY,nDstHeight, 2046*cdf0e10cSrcweir nOffX,nDstWidth, 2047*cdf0e10cSrcweir pMapX,pMapY ); 2048*cdf0e10cSrcweir } 2049*cdf0e10cSrcweir else 2050*cdf0e10cSrcweir { 2051*cdf0e10cSrcweir aTmp = ImplBlend( 2052*cdf0e10cSrcweir aBmp,pP,pA, 2053*cdf0e10cSrcweir nOffY,nDstHeight, 2054*cdf0e10cSrcweir nOffX,nDstWidth, 2055*cdf0e10cSrcweir aBmpRect,aOutSz, 2056*cdf0e10cSrcweir bHMirr,bVMirr, 2057*cdf0e10cSrcweir pMapX,pMapY ); 2058*cdf0e10cSrcweir } 2059*cdf0e10cSrcweir 2060*cdf0e10cSrcweir // #110958# Disable alpha VDev, we're doing the necessary 2061*cdf0e10cSrcweir // stuff explicitely furher below 2062*cdf0e10cSrcweir if( mpAlphaVDev ) 2063*cdf0e10cSrcweir mpAlphaVDev = NULL; 2064*cdf0e10cSrcweir 2065*cdf0e10cSrcweir DrawBitmap( aDstRect.TopLeft(), 2066*cdf0e10cSrcweir aTmp ); 2067*cdf0e10cSrcweir 2068*cdf0e10cSrcweir // #110958# Enable alpha VDev again 2069*cdf0e10cSrcweir mpAlphaVDev = pOldVDev; 2070*cdf0e10cSrcweir } 2071*cdf0e10cSrcweir 2072*cdf0e10cSrcweir ( (Bitmap&) rBmp ).ReleaseAccess( pP ); 2073*cdf0e10cSrcweir ( (AlphaMask&) rAlpha ).ReleaseAccess( pA ); 2074*cdf0e10cSrcweir 2075*cdf0e10cSrcweir delete[] pMapX; 2076*cdf0e10cSrcweir delete[] pMapY; 2077*cdf0e10cSrcweir mbMap = bOldMap; 2078*cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 2079*cdf0e10cSrcweir } 2080*cdf0e10cSrcweir } 2081*cdf0e10cSrcweir } 2082*cdf0e10cSrcweir 2083*cdf0e10cSrcweir // ------------------------------------------------------------------------ 2084*cdf0e10cSrcweir 2085*cdf0e10cSrcweir void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask, 2086*cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize, 2087*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel ) 2088*cdf0e10cSrcweir { 2089*cdf0e10cSrcweir Point aPt; 2090*cdf0e10cSrcweir Point aDestPt( LogicToPixel( rDestPt ) ); 2091*cdf0e10cSrcweir Size aDestSz( LogicToPixel( rDestSize ) ); 2092*cdf0e10cSrcweir Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel ); 2093*cdf0e10cSrcweir 2094*cdf0e10cSrcweir aSrcRect.Justify(); 2095*cdf0e10cSrcweir 2096*cdf0e10cSrcweir if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() ) 2097*cdf0e10cSrcweir { 2098*cdf0e10cSrcweir Bitmap aPaint( rBmp ), aMask( rMask ); 2099*cdf0e10cSrcweir sal_uLong nMirrFlags = 0UL; 2100*cdf0e10cSrcweir 2101*cdf0e10cSrcweir if( aMask.GetBitCount() > 1 ) 2102*cdf0e10cSrcweir aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); 2103*cdf0e10cSrcweir 2104*cdf0e10cSrcweir // mirrored horizontically 2105*cdf0e10cSrcweir if( aDestSz.Width() < 0L ) 2106*cdf0e10cSrcweir { 2107*cdf0e10cSrcweir aDestSz.Width() = -aDestSz.Width(); 2108*cdf0e10cSrcweir aDestPt.X() -= ( aDestSz.Width() - 1L ); 2109*cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ; 2110*cdf0e10cSrcweir } 2111*cdf0e10cSrcweir 2112*cdf0e10cSrcweir // mirrored vertically 2113*cdf0e10cSrcweir if( aDestSz.Height() < 0L ) 2114*cdf0e10cSrcweir { 2115*cdf0e10cSrcweir aDestSz.Height() = -aDestSz.Height(); 2116*cdf0e10cSrcweir aDestPt.Y() -= ( aDestSz.Height() - 1L ); 2117*cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT; 2118*cdf0e10cSrcweir } 2119*cdf0e10cSrcweir 2120*cdf0e10cSrcweir // source cropped? 2121*cdf0e10cSrcweir if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) ) 2122*cdf0e10cSrcweir { 2123*cdf0e10cSrcweir aPaint.Crop( aSrcRect ); 2124*cdf0e10cSrcweir aMask.Crop( aSrcRect ); 2125*cdf0e10cSrcweir } 2126*cdf0e10cSrcweir 2127*cdf0e10cSrcweir // destination mirrored 2128*cdf0e10cSrcweir if( nMirrFlags ) 2129*cdf0e10cSrcweir { 2130*cdf0e10cSrcweir aPaint.Mirror( nMirrFlags ); 2131*cdf0e10cSrcweir aMask.Mirror( nMirrFlags ); 2132*cdf0e10cSrcweir } 2133*cdf0e10cSrcweir 2134*cdf0e10cSrcweir // we always want to have a mask 2135*cdf0e10cSrcweir if( aMask.IsEmpty() ) 2136*cdf0e10cSrcweir { 2137*cdf0e10cSrcweir aMask = Bitmap( aSrcRect.GetSize(), 1 ); 2138*cdf0e10cSrcweir aMask.Erase( Color( COL_BLACK ) ); 2139*cdf0e10cSrcweir } 2140*cdf0e10cSrcweir 2141*cdf0e10cSrcweir // do painting 2142*cdf0e10cSrcweir const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight(); 2143*cdf0e10cSrcweir long nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight; 2144*cdf0e10cSrcweir long* pMapX = new long[ nSrcWidth + 1 ]; 2145*cdf0e10cSrcweir long* pMapY = new long[ nSrcHeight + 1 ]; 2146*cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 2147*cdf0e10cSrcweir 2148*cdf0e10cSrcweir mbMap = sal_False; 2149*cdf0e10cSrcweir 2150*cdf0e10cSrcweir // create forward mapping tables 2151*cdf0e10cSrcweir for( nX = 0L; nX <= nSrcWidth; nX++ ) 2152*cdf0e10cSrcweir pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth ); 2153*cdf0e10cSrcweir 2154*cdf0e10cSrcweir for( nY = 0L; nY <= nSrcHeight; nY++ ) 2155*cdf0e10cSrcweir pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight ); 2156*cdf0e10cSrcweir 2157*cdf0e10cSrcweir // walk through all rectangles of mask 2158*cdf0e10cSrcweir Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) ); 2159*cdf0e10cSrcweir ImplRegionInfo aInfo; 2160*cdf0e10cSrcweir sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2161*cdf0e10cSrcweir 2162*cdf0e10cSrcweir while( bRgnRect ) 2163*cdf0e10cSrcweir { 2164*cdf0e10cSrcweir Bitmap aBandBmp( aPaint ); 2165*cdf0e10cSrcweir const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) ); 2166*cdf0e10cSrcweir const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] ); 2167*cdf0e10cSrcweir const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() ); 2168*cdf0e10cSrcweir 2169*cdf0e10cSrcweir aBandBmp.Crop( aBandRect ); 2170*cdf0e10cSrcweir ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION ); 2171*cdf0e10cSrcweir bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2172*cdf0e10cSrcweir } 2173*cdf0e10cSrcweir 2174*cdf0e10cSrcweir mbMap = bOldMap; 2175*cdf0e10cSrcweir 2176*cdf0e10cSrcweir delete[] pMapX; 2177*cdf0e10cSrcweir delete[] pMapY; 2178*cdf0e10cSrcweir } 2179*cdf0e10cSrcweir } 2180*cdf0e10cSrcweir 2181*cdf0e10cSrcweir // ------------------------------------------------------------------------ 2182*cdf0e10cSrcweir 2183*cdf0e10cSrcweir void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor, 2184*cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize, 2185*cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel ) 2186*cdf0e10cSrcweir { 2187*cdf0e10cSrcweir Point aPt; 2188*cdf0e10cSrcweir Point aDestPt( LogicToPixel( rDestPt ) ); 2189*cdf0e10cSrcweir Size aDestSz( LogicToPixel( rDestSize ) ); 2190*cdf0e10cSrcweir Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel ); 2191*cdf0e10cSrcweir 2192*cdf0e10cSrcweir aSrcRect.Justify(); 2193*cdf0e10cSrcweir 2194*cdf0e10cSrcweir if( !rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() ) 2195*cdf0e10cSrcweir { 2196*cdf0e10cSrcweir Bitmap aMask( rMask ); 2197*cdf0e10cSrcweir sal_uLong nMirrFlags = 0UL; 2198*cdf0e10cSrcweir 2199*cdf0e10cSrcweir if( aMask.GetBitCount() > 1 ) 2200*cdf0e10cSrcweir aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); 2201*cdf0e10cSrcweir 2202*cdf0e10cSrcweir // mirrored horizontically 2203*cdf0e10cSrcweir if( aDestSz.Width() < 0L ) 2204*cdf0e10cSrcweir { 2205*cdf0e10cSrcweir aDestSz.Width() = -aDestSz.Width(); 2206*cdf0e10cSrcweir aDestPt.X() -= ( aDestSz.Width() - 1L ); 2207*cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ; 2208*cdf0e10cSrcweir } 2209*cdf0e10cSrcweir 2210*cdf0e10cSrcweir // mirrored vertically 2211*cdf0e10cSrcweir if( aDestSz.Height() < 0L ) 2212*cdf0e10cSrcweir { 2213*cdf0e10cSrcweir aDestSz.Height() = -aDestSz.Height(); 2214*cdf0e10cSrcweir aDestPt.Y() -= ( aDestSz.Height() - 1L ); 2215*cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT; 2216*cdf0e10cSrcweir } 2217*cdf0e10cSrcweir 2218*cdf0e10cSrcweir // source cropped? 2219*cdf0e10cSrcweir if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) ) 2220*cdf0e10cSrcweir aMask.Crop( aSrcRect ); 2221*cdf0e10cSrcweir 2222*cdf0e10cSrcweir // destination mirrored 2223*cdf0e10cSrcweir if( nMirrFlags ) 2224*cdf0e10cSrcweir aMask.Mirror( nMirrFlags ); 2225*cdf0e10cSrcweir 2226*cdf0e10cSrcweir // do painting 2227*cdf0e10cSrcweir const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight(); 2228*cdf0e10cSrcweir long nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight; 2229*cdf0e10cSrcweir long* pMapX = new long[ nSrcWidth + 1 ]; 2230*cdf0e10cSrcweir long* pMapY = new long[ nSrcHeight + 1 ]; 2231*cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 2232*cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 2233*cdf0e10cSrcweir 2234*cdf0e10cSrcweir mpMetaFile = NULL; 2235*cdf0e10cSrcweir mbMap = sal_False; 2236*cdf0e10cSrcweir Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); 2237*cdf0e10cSrcweir SetLineColor( rMaskColor ); 2238*cdf0e10cSrcweir SetFillColor( rMaskColor ); 2239*cdf0e10cSrcweir ImplInitLineColor(); 2240*cdf0e10cSrcweir ImplInitFillColor(); 2241*cdf0e10cSrcweir 2242*cdf0e10cSrcweir // create forward mapping tables 2243*cdf0e10cSrcweir for( nX = 0L; nX <= nSrcWidth; nX++ ) 2244*cdf0e10cSrcweir pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth ); 2245*cdf0e10cSrcweir 2246*cdf0e10cSrcweir for( nY = 0L; nY <= nSrcHeight; nY++ ) 2247*cdf0e10cSrcweir pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight ); 2248*cdf0e10cSrcweir 2249*cdf0e10cSrcweir // walk through all rectangles of mask 2250*cdf0e10cSrcweir Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) ); 2251*cdf0e10cSrcweir ImplRegionInfo aInfo; 2252*cdf0e10cSrcweir sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2253*cdf0e10cSrcweir 2254*cdf0e10cSrcweir while( bRgnRect ) 2255*cdf0e10cSrcweir { 2256*cdf0e10cSrcweir const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] ); 2257*cdf0e10cSrcweir const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() ); 2258*cdf0e10cSrcweir 2259*cdf0e10cSrcweir DrawRect( Rectangle( aMapPt, aMapSz ) ); 2260*cdf0e10cSrcweir bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2261*cdf0e10cSrcweir } 2262*cdf0e10cSrcweir 2263*cdf0e10cSrcweir Pop(); 2264*cdf0e10cSrcweir delete[] pMapX; 2265*cdf0e10cSrcweir delete[] pMapY; 2266*cdf0e10cSrcweir mbMap = bOldMap; 2267*cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 2268*cdf0e10cSrcweir } 2269*cdf0e10cSrcweir } 2270