19f62ea84SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file 59f62ea84SAndrew Rist * distributed with this work for additional information 69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file 79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the 89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance 99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing, 149f62ea84SAndrew Rist * software distributed under the License is distributed on an 159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the 179f62ea84SAndrew Rist * specific language governing permissions and limitations 189f62ea84SAndrew Rist * under the License. 19cdf0e10cSrcweir * 209f62ea84SAndrew Rist *************************************************************/ 219f62ea84SAndrew Rist 22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 23cdf0e10cSrcweir #include "precompiled_vcl.hxx" 24cdf0e10cSrcweir 25cdf0e10cSrcweir #include <tools/debug.hxx> 26cdf0e10cSrcweir #include <vcl/bitmap.hxx> 27cdf0e10cSrcweir #include <vcl/bitmapex.hxx> 28cdf0e10cSrcweir #include <vcl/window.hxx> 29cdf0e10cSrcweir #include <vcl/metaact.hxx> 30cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 31cdf0e10cSrcweir #include <vcl/virdev.hxx> 32cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 33cdf0e10cSrcweir #include <vcl/outdev.hxx> 34cdf0e10cSrcweir #include <vcl/window.hxx> 35cdf0e10cSrcweir #include <vcl/image.hxx> 36cdf0e10cSrcweir #include <bmpfast.hxx> 37cdf0e10cSrcweir #include <salbmp.hxx> 38cdf0e10cSrcweir #include <salgdi.hxx> 39cdf0e10cSrcweir #include <impbmp.hxx> 40cdf0e10cSrcweir #include <sallayout.hxx> 41cdf0e10cSrcweir #include <image.h> 42cdf0e10cSrcweir #include <outdev.h> 43cdf0e10cSrcweir #include <window.h> 44cdf0e10cSrcweir #include <outdata.hxx> 455f27b83cSArmin Le Grand #include <basegfx/matrix/b2dhommatrix.hxx> 46f8c0d554SArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx> 47cdf0e10cSrcweir 48cdf0e10cSrcweir #define BAND_MAX_SIZE 512000 49cdf0e10cSrcweir 50cdf0e10cSrcweir // ======================================================================= 51cdf0e10cSrcweir 52cdf0e10cSrcweir DBG_NAMEEX( OutputDevice ) 53cdf0e10cSrcweir 54cdf0e10cSrcweir // ======================================================================= 55cdf0e10cSrcweir 56cdf0e10cSrcweir // ----------- 57cdf0e10cSrcweir // - Defines - 58cdf0e10cSrcweir // ----------- 59cdf0e10cSrcweir 60cdf0e10cSrcweir #define OUTDEV_INIT() \ 61cdf0e10cSrcweir { \ 62cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() ) \ 63cdf0e10cSrcweir return; \ 64cdf0e10cSrcweir \ 65cdf0e10cSrcweir if ( !mpGraphics ) \ 66cdf0e10cSrcweir if ( !ImplGetGraphics() ) \ 67cdf0e10cSrcweir return; \ 68cdf0e10cSrcweir \ 69cdf0e10cSrcweir if ( mbInitClipRegion ) \ 70cdf0e10cSrcweir ImplInitClipRegion(); \ 71cdf0e10cSrcweir \ 72cdf0e10cSrcweir if ( mbOutputClipped ) \ 73cdf0e10cSrcweir return; \ 74cdf0e10cSrcweir } 75cdf0e10cSrcweir 76cdf0e10cSrcweir // ------------- 77cdf0e10cSrcweir // - externals - 78cdf0e10cSrcweir // ------------- 79cdf0e10cSrcweir 80cdf0e10cSrcweir extern sal_uLong nVCLRLut[ 6 ]; 81cdf0e10cSrcweir extern sal_uLong nVCLGLut[ 6 ]; 82cdf0e10cSrcweir extern sal_uLong nVCLBLut[ 6 ]; 83cdf0e10cSrcweir extern sal_uLong nVCLDitherLut[ 256 ]; 84cdf0e10cSrcweir extern sal_uLong nVCLLut[ 256 ]; 85cdf0e10cSrcweir 86cdf0e10cSrcweir // ======================================================================= 87cdf0e10cSrcweir 885f27b83cSArmin Le Grand sal_uLong ImplAdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix ) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir sal_uLong nMirrFlags = 0; 91cdf0e10cSrcweir 92cdf0e10cSrcweir if ( rTwoRect.mnDestWidth < 0 ) 93cdf0e10cSrcweir { 94cdf0e10cSrcweir rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth; 95cdf0e10cSrcweir rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth; 96cdf0e10cSrcweir rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1; 97cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ; 98cdf0e10cSrcweir } 99cdf0e10cSrcweir 100cdf0e10cSrcweir if ( rTwoRect.mnDestHeight < 0 ) 101cdf0e10cSrcweir { 102cdf0e10cSrcweir rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight; 103cdf0e10cSrcweir rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight; 104cdf0e10cSrcweir rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1; 105cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT; 106cdf0e10cSrcweir } 107cdf0e10cSrcweir 108cdf0e10cSrcweir if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) || 109cdf0e10cSrcweir ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) || 110cdf0e10cSrcweir ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) || 111cdf0e10cSrcweir ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) ) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ), 114cdf0e10cSrcweir Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) ); 115cdf0e10cSrcweir Rectangle aCropRect( aSourceRect ); 116cdf0e10cSrcweir 117cdf0e10cSrcweir aCropRect.Intersection( Rectangle( Point(), rSizePix ) ); 118cdf0e10cSrcweir 119cdf0e10cSrcweir if( aCropRect.IsEmpty() ) 120cdf0e10cSrcweir rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0; 121cdf0e10cSrcweir else 122cdf0e10cSrcweir { 123cdf0e10cSrcweir const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0; 124cdf0e10cSrcweir const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0; 125cdf0e10cSrcweir 126cdf0e10cSrcweir const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) ); 127cdf0e10cSrcweir const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) ); 128cdf0e10cSrcweir const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) ); 129cdf0e10cSrcweir const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) ); 130cdf0e10cSrcweir 131cdf0e10cSrcweir rTwoRect.mnSrcX = aCropRect.Left(); 132cdf0e10cSrcweir rTwoRect.mnSrcY = aCropRect.Top(); 133cdf0e10cSrcweir rTwoRect.mnSrcWidth = aCropRect.GetWidth(); 134cdf0e10cSrcweir rTwoRect.mnSrcHeight = aCropRect.GetHeight(); 135cdf0e10cSrcweir rTwoRect.mnDestX = nDstX1; 136cdf0e10cSrcweir rTwoRect.mnDestY = nDstY1; 137cdf0e10cSrcweir rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1; 138cdf0e10cSrcweir rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1; 139cdf0e10cSrcweir } 140cdf0e10cSrcweir } 141cdf0e10cSrcweir 142cdf0e10cSrcweir return nMirrFlags; 143cdf0e10cSrcweir } 144cdf0e10cSrcweir 145cdf0e10cSrcweir // ======================================================================= 146cdf0e10cSrcweir 1475f27b83cSArmin Le Grand void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, SalTwoRect& rPosAry ) 148cdf0e10cSrcweir { 149cdf0e10cSrcweir SalGraphics* pGraphics2; 150cdf0e10cSrcweir 1515f27b83cSArmin Le Grand if ( rPosAry.mnSrcWidth && rPosAry.mnSrcHeight && rPosAry.mnDestWidth && rPosAry.mnDestHeight ) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir if ( this == pSrcDev ) 154cdf0e10cSrcweir pGraphics2 = NULL; 155cdf0e10cSrcweir else 156cdf0e10cSrcweir { 157cdf0e10cSrcweir if ( (GetOutDevType() != pSrcDev->GetOutDevType()) || 158cdf0e10cSrcweir (GetOutDevType() != OUTDEV_WINDOW) ) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir if ( !pSrcDev->mpGraphics ) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() ) 163cdf0e10cSrcweir return; 164cdf0e10cSrcweir } 165cdf0e10cSrcweir pGraphics2 = pSrcDev->mpGraphics; 166cdf0e10cSrcweir } 167cdf0e10cSrcweir else 168cdf0e10cSrcweir { 169cdf0e10cSrcweir if ( ((Window*)this)->mpWindowImpl->mpFrameWindow == ((Window*)pSrcDev)->mpWindowImpl->mpFrameWindow ) 170cdf0e10cSrcweir pGraphics2 = NULL; 171cdf0e10cSrcweir else 172cdf0e10cSrcweir { 173cdf0e10cSrcweir if ( !pSrcDev->mpGraphics ) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() ) 176cdf0e10cSrcweir return; 177cdf0e10cSrcweir } 178cdf0e10cSrcweir pGraphics2 = pSrcDev->mpGraphics; 179cdf0e10cSrcweir 180cdf0e10cSrcweir if ( !mpGraphics ) 181cdf0e10cSrcweir { 182cdf0e10cSrcweir if ( !ImplGetGraphics() ) 183cdf0e10cSrcweir return; 184cdf0e10cSrcweir } 185cdf0e10cSrcweir DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics, 186cdf0e10cSrcweir "OutputDevice::DrawOutDev(): We need more than one Graphics" ); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir } 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir // #102532# Offset only has to be pseudo window offset 192cdf0e10cSrcweir Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ), 193cdf0e10cSrcweir Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) ); 1945f27b83cSArmin Le Grand Rectangle aSrcRect( Point( rPosAry.mnSrcX, rPosAry.mnSrcY ), 1955f27b83cSArmin Le Grand Size( rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ) ); 196cdf0e10cSrcweir const long nOldRight = aSrcRect.Right(); 197cdf0e10cSrcweir const long nOldBottom = aSrcRect.Bottom(); 198cdf0e10cSrcweir 199cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() ) 200cdf0e10cSrcweir { 2015f27b83cSArmin Le Grand if ( (rPosAry.mnSrcX+rPosAry.mnSrcWidth-1) > aSrcOutRect.Right() ) 202cdf0e10cSrcweir { 2035f27b83cSArmin Le Grand const long nOldWidth = rPosAry.mnSrcWidth; 2045f27b83cSArmin Le Grand rPosAry.mnSrcWidth -= (nOldRight - aSrcRect.Right()); 2055f27b83cSArmin Le Grand rPosAry.mnDestWidth = rPosAry.mnDestWidth * rPosAry.mnSrcWidth / nOldWidth; 206cdf0e10cSrcweir } 207cdf0e10cSrcweir 2085f27b83cSArmin Le Grand if ( (rPosAry.mnSrcY+rPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() ) 209cdf0e10cSrcweir { 2105f27b83cSArmin Le Grand const long nOldHeight = rPosAry.mnSrcHeight; 2115f27b83cSArmin Le Grand rPosAry.mnSrcHeight -= (nOldBottom - aSrcRect.Bottom()); 2125f27b83cSArmin Le Grand rPosAry.mnDestHeight = rPosAry.mnDestHeight * rPosAry.mnSrcHeight / nOldHeight; 213cdf0e10cSrcweir } 214cdf0e10cSrcweir 215cdf0e10cSrcweir // --- RTL --- if this is no window, but pSrcDev is a window 216cdf0e10cSrcweir // mirroring may be required 217cdf0e10cSrcweir // because only windows have a SalGraphicsLayout 218cdf0e10cSrcweir // mirroring is performed here 219cdf0e10cSrcweir if( (GetOutDevType() != OUTDEV_WINDOW) && pGraphics2 && (pGraphics2->GetLayout() & SAL_LAYOUT_BIDI_RTL) ) 220cdf0e10cSrcweir { 2215f27b83cSArmin Le Grand SalTwoRect aPosAry2 = rPosAry; 2225f27b83cSArmin Le Grand pGraphics2->mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcDev ); 2235f27b83cSArmin Le Grand mpGraphics->CopyBits( aPosAry2, pGraphics2, this, pSrcDev ); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir else 2265f27b83cSArmin Le Grand mpGraphics->CopyBits( rPosAry, pGraphics2, this, pSrcDev ); 227cdf0e10cSrcweir } 228cdf0e10cSrcweir } 229cdf0e10cSrcweir } 230cdf0e10cSrcweir 231cdf0e10cSrcweir // ------------------------------------------------------------------ 232cdf0e10cSrcweir 233cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize, 234cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize ) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawOutDev()" ); 237cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 238cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" ); 239cdf0e10cSrcweir 240cdf0e10cSrcweir if( ImplIsRecordLayout() ) 241cdf0e10cSrcweir return; 242cdf0e10cSrcweir 243cdf0e10cSrcweir if ( meOutDevType == OUTDEV_PRINTER ) 244cdf0e10cSrcweir return; 245cdf0e10cSrcweir 246cdf0e10cSrcweir if ( ROP_INVERT == meRasterOp ) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 249cdf0e10cSrcweir return; 250cdf0e10cSrcweir } 251cdf0e10cSrcweir 252cdf0e10cSrcweir if ( mpMetaFile ) 253cdf0e10cSrcweir { 254cdf0e10cSrcweir const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) ); 255cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) ); 256cdf0e10cSrcweir } 257cdf0e10cSrcweir 258cdf0e10cSrcweir OUTDEV_INIT(); 259cdf0e10cSrcweir 2605f27b83cSArmin Le Grand SalTwoRect aPosAry; 261cdf0e10cSrcweir aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() ); 262cdf0e10cSrcweir aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() ); 263cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 264cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 265cdf0e10cSrcweir 266cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 267cdf0e10cSrcweir { 268cdf0e10cSrcweir aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() ); 269cdf0e10cSrcweir aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() ); 270cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 271cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 272cdf0e10cSrcweir 273cdf0e10cSrcweir Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ), 274cdf0e10cSrcweir Size( mnOutWidth, mnOutHeight ) ); 275cdf0e10cSrcweir Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ), 276cdf0e10cSrcweir Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) ); 277cdf0e10cSrcweir long nOldRight = aSrcRect.Right(); 278cdf0e10cSrcweir long nOldBottom = aSrcRect.Bottom(); 279cdf0e10cSrcweir 280cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() ) 281cdf0e10cSrcweir { 282cdf0e10cSrcweir if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() ) 283cdf0e10cSrcweir { 284cdf0e10cSrcweir long nOldWidth = aPosAry.mnSrcWidth; 285cdf0e10cSrcweir aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right(); 286cdf0e10cSrcweir aPosAry.mnDestWidth = aPosAry.mnDestWidth*aPosAry.mnSrcWidth/nOldWidth; 287cdf0e10cSrcweir } 288cdf0e10cSrcweir 289cdf0e10cSrcweir if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() ) 290cdf0e10cSrcweir { 291cdf0e10cSrcweir long nOldHeight = aPosAry.mnSrcHeight; 292cdf0e10cSrcweir aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom(); 293cdf0e10cSrcweir aPosAry.mnDestHeight = aPosAry.mnDestHeight*aPosAry.mnSrcHeight/nOldHeight; 294cdf0e10cSrcweir } 295cdf0e10cSrcweir 2965f27b83cSArmin Le Grand mpGraphics->CopyBits( aPosAry, NULL, this, NULL ); 297cdf0e10cSrcweir } 298cdf0e10cSrcweir } 299cdf0e10cSrcweir 300cdf0e10cSrcweir if( mpAlphaVDev ) 301cdf0e10cSrcweir mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize ); 302cdf0e10cSrcweir } 303cdf0e10cSrcweir 304cdf0e10cSrcweir // ------------------------------------------------------------------ 305cdf0e10cSrcweir 306cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize, 307cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize, 308cdf0e10cSrcweir const OutputDevice& rOutDev ) 309cdf0e10cSrcweir { 310cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawOutDev()" ); 311cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 312cdf0e10cSrcweir DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice ); 313cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" ); 314cdf0e10cSrcweir DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" ); 315cdf0e10cSrcweir 316cdf0e10cSrcweir if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) || ImplIsRecordLayout() ) 317cdf0e10cSrcweir return; 318cdf0e10cSrcweir 319cdf0e10cSrcweir if ( ROP_INVERT == meRasterOp ) 320cdf0e10cSrcweir { 321cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 322cdf0e10cSrcweir return; 323cdf0e10cSrcweir } 324cdf0e10cSrcweir 325cdf0e10cSrcweir if ( mpMetaFile ) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) ); 328cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) ); 329cdf0e10cSrcweir } 330cdf0e10cSrcweir 331cdf0e10cSrcweir OUTDEV_INIT(); 332cdf0e10cSrcweir 3335f27b83cSArmin Le Grand SalTwoRect aPosAry; 334cdf0e10cSrcweir aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() ); 335cdf0e10cSrcweir aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() ); 336cdf0e10cSrcweir aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() ); 337cdf0e10cSrcweir aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() ); 338cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 339cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 340cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 341cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 342cdf0e10cSrcweir 343cdf0e10cSrcweir if( mpAlphaVDev ) 344cdf0e10cSrcweir { 345cdf0e10cSrcweir if( rOutDev.mpAlphaVDev ) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir // alpha-blend source over destination 348cdf0e10cSrcweir DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) ); 349cdf0e10cSrcweir 350cdf0e10cSrcweir // This would be mode SOURCE: 351cdf0e10cSrcweir // copy source alpha channel to our alpha channel 352cdf0e10cSrcweir //mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev ); 353cdf0e10cSrcweir } 354cdf0e10cSrcweir else 355cdf0e10cSrcweir { 3565f27b83cSArmin Le Grand ImplDrawOutDevDirect( &rOutDev, aPosAry ); 357cdf0e10cSrcweir 358cdf0e10cSrcweir // #i32109#: make destination rectangle opaque - source has no alpha 359cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 360cdf0e10cSrcweir } 361cdf0e10cSrcweir } 362cdf0e10cSrcweir else 363cdf0e10cSrcweir { 364cdf0e10cSrcweir if( rOutDev.mpAlphaVDev ) 365cdf0e10cSrcweir { 366cdf0e10cSrcweir // alpha-blend source over destination 367cdf0e10cSrcweir DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) ); 368cdf0e10cSrcweir } 369cdf0e10cSrcweir else 370cdf0e10cSrcweir { 371cdf0e10cSrcweir // no alpha at all, neither in source nor destination device 3725f27b83cSArmin Le Grand ImplDrawOutDevDirect( &rOutDev, aPosAry ); 373cdf0e10cSrcweir } 374cdf0e10cSrcweir } 375cdf0e10cSrcweir } 376cdf0e10cSrcweir 377cdf0e10cSrcweir // ------------------------------------------------------------------ 378cdf0e10cSrcweir 379cdf0e10cSrcweir void OutputDevice::CopyArea( const Point& rDestPt, 380cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize, 381cdf0e10cSrcweir sal_uInt16 nFlags ) 382cdf0e10cSrcweir { 383cdf0e10cSrcweir DBG_TRACE( "OutputDevice::CopyArea()" ); 384cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 385cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" ); 386cdf0e10cSrcweir 387cdf0e10cSrcweir if ( meOutDevType == OUTDEV_PRINTER || ImplIsRecordLayout() ) 388cdf0e10cSrcweir return; 389cdf0e10cSrcweir 390cdf0e10cSrcweir RasterOp eOldRop = GetRasterOp(); 391cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT ); 392cdf0e10cSrcweir 393cdf0e10cSrcweir OUTDEV_INIT(); 394cdf0e10cSrcweir 3955f27b83cSArmin Le Grand SalTwoRect aPosAry; 396cdf0e10cSrcweir aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() ); 397cdf0e10cSrcweir aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() ); 398cdf0e10cSrcweir 399cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight ) 400cdf0e10cSrcweir { 401cdf0e10cSrcweir aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() ); 402cdf0e10cSrcweir aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() ); 403cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 404cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 405cdf0e10cSrcweir 406cdf0e10cSrcweir Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ), 407cdf0e10cSrcweir Size( mnOutWidth, mnOutHeight ) ); 408cdf0e10cSrcweir Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ), 409cdf0e10cSrcweir Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) ); 410cdf0e10cSrcweir long nOldRight = aSrcRect.Right(); 411cdf0e10cSrcweir long nOldBottom = aSrcRect.Bottom(); 412cdf0e10cSrcweir 413cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() ) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() ) 416cdf0e10cSrcweir aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right(); 417cdf0e10cSrcweir 418cdf0e10cSrcweir if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() ) 419cdf0e10cSrcweir aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom(); 420cdf0e10cSrcweir 421cdf0e10cSrcweir if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) ) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir ((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect, 424cdf0e10cSrcweir aPosAry.mnDestX-aPosAry.mnSrcX, 425cdf0e10cSrcweir aPosAry.mnDestY-aPosAry.mnSrcY, 426cdf0e10cSrcweir sal_False ); 427cdf0e10cSrcweir 428cdf0e10cSrcweir mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY, 429cdf0e10cSrcweir aPosAry.mnSrcX, aPosAry.mnSrcY, 430cdf0e10cSrcweir aPosAry.mnSrcWidth, aPosAry.mnSrcHeight, 431cdf0e10cSrcweir SAL_COPYAREA_WINDOWINVALIDATE, this ); 432cdf0e10cSrcweir } 433cdf0e10cSrcweir else 434cdf0e10cSrcweir { 435cdf0e10cSrcweir aPosAry.mnDestWidth = aPosAry.mnSrcWidth; 436cdf0e10cSrcweir aPosAry.mnDestHeight = aPosAry.mnSrcHeight; 4375f27b83cSArmin Le Grand mpGraphics->CopyBits( aPosAry, NULL, this, NULL ); 438cdf0e10cSrcweir } 439cdf0e10cSrcweir } 440cdf0e10cSrcweir } 441cdf0e10cSrcweir 442cdf0e10cSrcweir SetRasterOp( eOldRop ); 443cdf0e10cSrcweir 444cdf0e10cSrcweir if( mpAlphaVDev ) 445cdf0e10cSrcweir mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags ); 446cdf0e10cSrcweir } 447cdf0e10cSrcweir 448cdf0e10cSrcweir // ------------------------------------------------------------------ 449cdf0e10cSrcweir 450cdf0e10cSrcweir void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize, 451cdf0e10cSrcweir const OutputDevice& rOutDev, const Region& rRegion ) 452cdf0e10cSrcweir { 453cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 454cdf0e10cSrcweir 455cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 456cdf0e10cSrcweir sal_Bool bOldMap = mbMap; 457cdf0e10cSrcweir RasterOp eOldROP = GetRasterOp(); 458cdf0e10cSrcweir mpMetaFile = NULL; 459cdf0e10cSrcweir mbMap = sal_False; 460cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT ); 461cdf0e10cSrcweir 462cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() ) 463cdf0e10cSrcweir return; 464cdf0e10cSrcweir 465cdf0e10cSrcweir if ( !mpGraphics ) 466cdf0e10cSrcweir { 467cdf0e10cSrcweir if ( !ImplGetGraphics() ) 468cdf0e10cSrcweir return; 469cdf0e10cSrcweir } 470cdf0e10cSrcweir 471cdf0e10cSrcweir // ClipRegion zuruecksetzen 472cdf0e10cSrcweir if ( rRegion.IsNull() ) 473cdf0e10cSrcweir mpGraphics->ResetClipRegion(); 474cdf0e10cSrcweir else 475cdf0e10cSrcweir ImplSelectClipRegion( rRegion ); 476cdf0e10cSrcweir 4775f27b83cSArmin Le Grand SalTwoRect aPosAry; 478cdf0e10cSrcweir aPosAry.mnSrcX = rDevPt.X(); 479cdf0e10cSrcweir aPosAry.mnSrcY = rDevPt.Y(); 480cdf0e10cSrcweir aPosAry.mnSrcWidth = rDevSize.Width(); 481cdf0e10cSrcweir aPosAry.mnSrcHeight = rDevSize.Height(); 482cdf0e10cSrcweir aPosAry.mnDestX = rPt.X(); 483cdf0e10cSrcweir aPosAry.mnDestY = rPt.Y(); 484cdf0e10cSrcweir aPosAry.mnDestWidth = rDevSize.Width(); 485cdf0e10cSrcweir aPosAry.mnDestHeight = rDevSize.Height(); 4865f27b83cSArmin Le Grand ImplDrawOutDevDirect( &rOutDev, aPosAry ); 487cdf0e10cSrcweir 488cdf0e10cSrcweir // Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird 489cdf0e10cSrcweir mbInitClipRegion = sal_True; 490cdf0e10cSrcweir 491cdf0e10cSrcweir SetRasterOp( eOldROP ); 492cdf0e10cSrcweir mbMap = bOldMap; 493cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 494cdf0e10cSrcweir } 495cdf0e10cSrcweir 496cdf0e10cSrcweir // ------------------------------------------------------------------ 497cdf0e10cSrcweir 498cdf0e10cSrcweir void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize, 499cdf0e10cSrcweir OutputDevice& rDev ) 500cdf0e10cSrcweir { 501cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 502cdf0e10cSrcweir 503cdf0e10cSrcweir sal_Bool bOldMap = mbMap; 504cdf0e10cSrcweir mbMap = sal_False; 505cdf0e10cSrcweir rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this ); 506cdf0e10cSrcweir mbMap = bOldMap; 507cdf0e10cSrcweir } 508cdf0e10cSrcweir 509cdf0e10cSrcweir // ------------------------------------------------------------------ 510cdf0e10cSrcweir 511cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap ) 512cdf0e10cSrcweir { 513cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap()" ); 514cdf0e10cSrcweir 515cdf0e10cSrcweir if( ImplIsRecordLayout() ) 516cdf0e10cSrcweir return; 517cdf0e10cSrcweir 518cdf0e10cSrcweir const Size aSizePix( rBitmap.GetSizePixel() ); 519cdf0e10cSrcweir ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION ); 520cdf0e10cSrcweir 521cdf0e10cSrcweir if( mpAlphaVDev ) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 524cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, PixelToLogic( aSizePix )) ); 525cdf0e10cSrcweir } 526cdf0e10cSrcweir } 527cdf0e10cSrcweir 528cdf0e10cSrcweir // ------------------------------------------------------------------ 529cdf0e10cSrcweir 530cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap ) 531cdf0e10cSrcweir { 532cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap( Size )" ); 533cdf0e10cSrcweir 534cdf0e10cSrcweir if( ImplIsRecordLayout() ) 535cdf0e10cSrcweir return; 536cdf0e10cSrcweir 537cdf0e10cSrcweir ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION ); 538cdf0e10cSrcweir 539cdf0e10cSrcweir if( mpAlphaVDev ) 540cdf0e10cSrcweir { 541cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 542cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 543cdf0e10cSrcweir } 544cdf0e10cSrcweir } 545cdf0e10cSrcweir 546cdf0e10cSrcweir // ------------------------------------------------------------------ 547cdf0e10cSrcweir 548cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, 549cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 550cdf0e10cSrcweir const Bitmap& rBitmap ) 551cdf0e10cSrcweir { 552cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" ); 553cdf0e10cSrcweir 554cdf0e10cSrcweir if( ImplIsRecordLayout() ) 555cdf0e10cSrcweir return; 556cdf0e10cSrcweir 557cdf0e10cSrcweir ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION ); 558cdf0e10cSrcweir 559cdf0e10cSrcweir if( mpAlphaVDev ) 560cdf0e10cSrcweir { 561cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 562cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 563cdf0e10cSrcweir } 564cdf0e10cSrcweir } 565cdf0e10cSrcweir 566cdf0e10cSrcweir // ----------------------------------------------------------------------------- 567cdf0e10cSrcweir 568cdf0e10cSrcweir void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize, 569cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 570cdf0e10cSrcweir const Bitmap& rBitmap, const sal_uLong nAction ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 573cdf0e10cSrcweir 574cdf0e10cSrcweir if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) ) 575cdf0e10cSrcweir return; 5765f27b83cSArmin Le Grand 5775f27b83cSArmin Le Grand if ( ROP_INVERT == meRasterOp ) 578cdf0e10cSrcweir { 579cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 580cdf0e10cSrcweir return; 581cdf0e10cSrcweir } 5825f27b83cSArmin Le Grand 5835f27b83cSArmin Le Grand Bitmap aBmp( rBitmap ); 5845f27b83cSArmin Le Grand 5855f27b83cSArmin Le Grand if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | 586cdf0e10cSrcweir DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) ) 587cdf0e10cSrcweir { 588cdf0e10cSrcweir if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) ) 589cdf0e10cSrcweir { 590cdf0e10cSrcweir sal_uInt8 cCmpVal; 591cdf0e10cSrcweir 592cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_BLACKBITMAP ) 593cdf0e10cSrcweir cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0; 594cdf0e10cSrcweir else 595cdf0e10cSrcweir cCmpVal = 255; 596cdf0e10cSrcweir 597cdf0e10cSrcweir Color aCol( cCmpVal, cCmpVal, cCmpVal ); 598cdf0e10cSrcweir Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 599cdf0e10cSrcweir SetLineColor( aCol ); 600cdf0e10cSrcweir SetFillColor( aCol ); 601cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 602cdf0e10cSrcweir Pop(); 603cdf0e10cSrcweir return; 604cdf0e10cSrcweir } 605cdf0e10cSrcweir else if( !!aBmp ) 606cdf0e10cSrcweir { 607cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GRAYBITMAP ) 608cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_8BIT_GREYS ); 609cdf0e10cSrcweir 610cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) 611cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_GHOSTED ); 612cdf0e10cSrcweir } 613cdf0e10cSrcweir } 614cdf0e10cSrcweir 615cdf0e10cSrcweir if ( mpMetaFile ) 616cdf0e10cSrcweir { 617cdf0e10cSrcweir switch( nAction ) 618cdf0e10cSrcweir { 619cdf0e10cSrcweir case( META_BMP_ACTION ): 620cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) ); 621cdf0e10cSrcweir break; 622cdf0e10cSrcweir 623cdf0e10cSrcweir case( META_BMPSCALE_ACTION ): 624cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) ); 625cdf0e10cSrcweir break; 626cdf0e10cSrcweir 627cdf0e10cSrcweir case( META_BMPSCALEPART_ACTION ): 628cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScalePartAction( 629cdf0e10cSrcweir rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) ); 630cdf0e10cSrcweir break; 631cdf0e10cSrcweir } 632cdf0e10cSrcweir } 633cdf0e10cSrcweir 634cdf0e10cSrcweir OUTDEV_INIT(); 635cdf0e10cSrcweir 636cdf0e10cSrcweir if( !aBmp.IsEmpty() ) 637cdf0e10cSrcweir { 6385f27b83cSArmin Le Grand SalTwoRect aPosAry; 639cdf0e10cSrcweir 640cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X(); 641cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y(); 642cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width(); 643cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height(); 644cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 645cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 646cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 647cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 648cdf0e10cSrcweir 649cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() ); 650cdf0e10cSrcweir 651cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 652cdf0e10cSrcweir { 653cdf0e10cSrcweir if ( nMirrFlags ) 654cdf0e10cSrcweir aBmp.Mirror( nMirrFlags ); 655cdf0e10cSrcweir 656cdf0e10cSrcweir /* #i75264# (corrected with #i81576#) 657cdf0e10cSrcweir * sometimes a bitmap is scaled to a ridiculous size and drawn 658cdf0e10cSrcweir * to a quite normal VDev, so only a very small part of 659cdf0e10cSrcweir * the scaled bitmap will be visible. However actually scaling 660cdf0e10cSrcweir * the bitmap will use so much memory that we end with a crash. 661cdf0e10cSrcweir * Workaround: since only a small part of the scaled bitmap will 662cdf0e10cSrcweir * be actually drawn anyway (because of clipping on the device 663cdf0e10cSrcweir * boundary), limit the destination and source rectangles so 664cdf0e10cSrcweir * that the destination rectangle will overlap the device but only 665cdf0e10cSrcweir * be reasonably (say factor 2) larger than the device itself. 666cdf0e10cSrcweir */ 6675f27b83cSArmin Le Grand 6685f27b83cSArmin Le Grand // not needed for win32, it uses GdiPlus and is able to do everything without 6695f27b83cSArmin Le Grand // internally scaling the bitmap 6705f27b83cSArmin Le Grand #ifndef WIN32 6715f27b83cSArmin Le Grand 672cdf0e10cSrcweir if( aPosAry.mnDestWidth > 2048 || aPosAry.mnDestHeight > 2048 ) 673cdf0e10cSrcweir { 674cdf0e10cSrcweir if( meOutDevType == OUTDEV_WINDOW || 675cdf0e10cSrcweir (meOutDevType == OUTDEV_VIRDEV && mpPDFWriter == 0 ) ) 676cdf0e10cSrcweir { 677cdf0e10cSrcweir // #i81576# do the following trick only if there is overlap at all 678cdf0e10cSrcweir // else the formulae don't work 679cdf0e10cSrcweir // theoretically in this case we wouldn't need to draw the bitmap at all 680cdf0e10cSrcweir // however there are some esoteric case where that is needed 681cdf0e10cSrcweir if( aPosAry.mnDestX + aPosAry.mnDestWidth >= 0 682cdf0e10cSrcweir && aPosAry.mnDestX < mnOutWidth 683cdf0e10cSrcweir && aPosAry.mnDestY + aPosAry.mnDestHeight >= 0 684cdf0e10cSrcweir && aPosAry.mnDestY < mnOutHeight ) 685cdf0e10cSrcweir { 686cdf0e10cSrcweir // reduce scaling to something reasonable taking into account the output size 687cdf0e10cSrcweir if( aPosAry.mnDestWidth > 3*mnOutWidth && aPosAry.mnSrcWidth ) 688cdf0e10cSrcweir { 689cdf0e10cSrcweir const double nScaleX = aPosAry.mnDestWidth/double(aPosAry.mnSrcWidth); 690cdf0e10cSrcweir 691cdf0e10cSrcweir if( aPosAry.mnDestX + aPosAry.mnDestWidth > mnOutWidth ) 692cdf0e10cSrcweir { 693cdf0e10cSrcweir aPosAry.mnDestWidth = Max(long(0),mnOutWidth-aPosAry.mnDestX); 694cdf0e10cSrcweir } 695cdf0e10cSrcweir if( aPosAry.mnDestX < 0 ) 696cdf0e10cSrcweir { 697cdf0e10cSrcweir aPosAry.mnDestWidth += aPosAry.mnDestX; 698cdf0e10cSrcweir aPosAry.mnSrcX -= sal::static_int_cast<long>(aPosAry.mnDestX / nScaleX); 699cdf0e10cSrcweir aPosAry.mnDestX = 0; 700cdf0e10cSrcweir } 701cdf0e10cSrcweir 702cdf0e10cSrcweir aPosAry.mnSrcWidth = sal::static_int_cast<long>(aPosAry.mnDestWidth / nScaleX); 703cdf0e10cSrcweir } 704cdf0e10cSrcweir 705cdf0e10cSrcweir if( aPosAry.mnDestHeight > 3*mnOutHeight && aPosAry.mnSrcHeight != 0 ) 706cdf0e10cSrcweir { 707cdf0e10cSrcweir const double nScaleY = aPosAry.mnDestHeight/double(aPosAry.mnSrcHeight); 708cdf0e10cSrcweir 709cdf0e10cSrcweir if( aPosAry.mnDestY + aPosAry.mnDestHeight > mnOutHeight ) 710cdf0e10cSrcweir { 711cdf0e10cSrcweir aPosAry.mnDestHeight = Max(long(0),mnOutHeight-aPosAry.mnDestY); 712cdf0e10cSrcweir } 713cdf0e10cSrcweir if( aPosAry.mnDestY < 0 ) 714cdf0e10cSrcweir { 715cdf0e10cSrcweir aPosAry.mnDestHeight += aPosAry.mnDestY; 716cdf0e10cSrcweir aPosAry.mnSrcY -= sal::static_int_cast<long>(aPosAry.mnDestY / nScaleY); 717cdf0e10cSrcweir aPosAry.mnDestY = 0; 718cdf0e10cSrcweir } 719cdf0e10cSrcweir 720cdf0e10cSrcweir aPosAry.mnSrcHeight = sal::static_int_cast<long>(aPosAry.mnDestHeight / nScaleY); 721cdf0e10cSrcweir } 722cdf0e10cSrcweir } 723cdf0e10cSrcweir } 724cdf0e10cSrcweir } 7255f27b83cSArmin Le Grand #endif 726cdf0e10cSrcweir 727cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 7285f27b83cSArmin Le Grand { 7295f27b83cSArmin Le Grand mpGraphics->DrawBitmap( aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this ); 7305f27b83cSArmin Le Grand } 731cdf0e10cSrcweir } 732cdf0e10cSrcweir } 733cdf0e10cSrcweir } 734cdf0e10cSrcweir 735cdf0e10cSrcweir // ------------------------------------------------------------------ 736cdf0e10cSrcweir 737cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, 738cdf0e10cSrcweir const BitmapEx& rBitmapEx ) 739cdf0e10cSrcweir { 740cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx()" ); 741cdf0e10cSrcweir 742cdf0e10cSrcweir if( ImplIsRecordLayout() ) 743cdf0e10cSrcweir return; 744cdf0e10cSrcweir 745cdf0e10cSrcweir if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() ) 7465f27b83cSArmin Le Grand { 747cdf0e10cSrcweir DrawBitmap( rDestPt, rBitmapEx.GetBitmap() ); 7485f27b83cSArmin Le Grand } 749cdf0e10cSrcweir else 750cdf0e10cSrcweir { 751cdf0e10cSrcweir const Size aSizePix( rBitmapEx.GetSizePixel() ); 752cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION ); 753cdf0e10cSrcweir } 754cdf0e10cSrcweir } 755cdf0e10cSrcweir 756cdf0e10cSrcweir // ------------------------------------------------------------------ 757cdf0e10cSrcweir 758cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize, 759cdf0e10cSrcweir const BitmapEx& rBitmapEx ) 760cdf0e10cSrcweir { 761cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" ); 762cdf0e10cSrcweir 763cdf0e10cSrcweir if( ImplIsRecordLayout() ) 764cdf0e10cSrcweir return; 765cdf0e10cSrcweir 766cdf0e10cSrcweir if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() ) 7675f27b83cSArmin Le Grand { 768cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() ); 7695f27b83cSArmin Le Grand } 770cdf0e10cSrcweir else 7715f27b83cSArmin Le Grand { 772cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION ); 773cdf0e10cSrcweir } 7745f27b83cSArmin Le Grand } 775cdf0e10cSrcweir 776cdf0e10cSrcweir // ------------------------------------------------------------------ 777cdf0e10cSrcweir 778cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize, 779cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 780cdf0e10cSrcweir const BitmapEx& rBitmapEx ) 781cdf0e10cSrcweir { 782cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" ); 783cdf0e10cSrcweir 784cdf0e10cSrcweir if( ImplIsRecordLayout() ) 785cdf0e10cSrcweir return; 786cdf0e10cSrcweir 787cdf0e10cSrcweir if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() ) 7885f27b83cSArmin Le Grand { 789cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() ); 7905f27b83cSArmin Le Grand } 791cdf0e10cSrcweir else 7925f27b83cSArmin Le Grand { 793cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION ); 794cdf0e10cSrcweir } 7955f27b83cSArmin Le Grand } 7965f27b83cSArmin Le Grand 7975f27b83cSArmin Le Grand // ------------------------------------------------------------------ 7985f27b83cSArmin Le Grand 7995f27b83cSArmin Le Grand void OutputDevice::DrawTransformedBitmapEx( 8005f27b83cSArmin Le Grand const basegfx::B2DHomMatrix& rTransformation, 8015f27b83cSArmin Le Grand const BitmapEx& rBitmapEx) 8025f27b83cSArmin Le Grand { 8035f27b83cSArmin Le Grand DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" ); 8045f27b83cSArmin Le Grand 8055f27b83cSArmin Le Grand if( ImplIsRecordLayout() ) 8065f27b83cSArmin Le Grand return; 8075f27b83cSArmin Le Grand 8085f27b83cSArmin Le Grand if(rBitmapEx.IsEmpty()) 8095f27b83cSArmin Le Grand return; 8105f27b83cSArmin Le Grand 8115f27b83cSArmin Le Grand if ( mnDrawMode & DRAWMODE_NOBITMAP ) 8125f27b83cSArmin Le Grand return; 8135f27b83cSArmin Le Grand 8145f27b83cSArmin Le Grand // decompose matrix to check rotation and shear 8155f27b83cSArmin Le Grand basegfx::B2DVector aScale, aTranslate; 8165f27b83cSArmin Le Grand double fRotate, fShearX; 8175f27b83cSArmin Le Grand rTransformation.decompose(aScale, aTranslate, fRotate, fShearX); 8185f27b83cSArmin Le Grand const bool bRotated(!basegfx::fTools::equalZero(fRotate)); 8195f27b83cSArmin Le Grand const bool bSheared(!basegfx::fTools::equalZero(fShearX)); 8205f27b83cSArmin Le Grand const bool bMirroredX(basegfx::fTools::less(aScale.getX(), 0.0)); 8215f27b83cSArmin Le Grand const bool bMirroredY(basegfx::fTools::less(aScale.getY(), 0.0)); 822f8c0d554SArmin Le Grand static bool bForceToOwnTransformer(false); 8235f27b83cSArmin Le Grand 824f8c0d554SArmin Le Grand if(!bForceToOwnTransformer && !bRotated && !bSheared && !bMirroredX && !bMirroredY) 8255f27b83cSArmin Le Grand { 8265f27b83cSArmin Le Grand // with no rotation, shear or mirroring it can be mapped to DrawBitmapEx 8275f27b83cSArmin Le Grand // do *not* execute the mirroring here, it's done in the fallback 828fa004bb0SArmin Le Grand // #124580# the correct DestSize needs to be calculated based on MaxXY values 8295f27b83cSArmin Le Grand const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY())); 830fa004bb0SArmin Le Grand const Size aDestSize( 831fa004bb0SArmin Le Grand basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(), 832fa004bb0SArmin Le Grand basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y()); 8335f27b83cSArmin Le Grand 8345f27b83cSArmin Le Grand DrawBitmapEx(aDestPt, aDestSize, rBitmapEx); 8355f27b83cSArmin Le Grand return; 8365f27b83cSArmin Le Grand } 8375f27b83cSArmin Le Grand 8385f27b83cSArmin Le Grand // we have rotation,shear or mirror, check if some crazy mode needs the 8395f27b83cSArmin Le Grand // created transformed bitmap 8405f27b83cSArmin Le Grand const bool bInvert(ROP_INVERT == meRasterOp); 8415f27b83cSArmin Le Grand const bool bBitmapChangedColor(mnDrawMode & (DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP)); 8425f27b83cSArmin Le Grand const bool bMetafile(mpMetaFile); 8435f27b83cSArmin Le Grand const bool bPrinter(OUTDEV_PRINTER == meOutDevType); 8445f27b83cSArmin Le Grand bool bDone(false); 8455f27b83cSArmin Le Grand const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation); 8465f27b83cSArmin Le Grand const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile && !bPrinter); 8475f27b83cSArmin Le Grand 848f8c0d554SArmin Le Grand if(!bForceToOwnTransformer && bTryDirectPaint) 8495f27b83cSArmin Le Grand { 8505f27b83cSArmin Le Grand // try to paint directly 8515f27b83cSArmin Le Grand const basegfx::B2DPoint aNull(aFullTransform * basegfx::B2DPoint(0.0, 0.0)); 8525f27b83cSArmin Le Grand const basegfx::B2DPoint aTopX(aFullTransform * basegfx::B2DPoint(1.0, 0.0)); 8535f27b83cSArmin Le Grand const basegfx::B2DPoint aTopY(aFullTransform * basegfx::B2DPoint(0.0, 1.0)); 8545f27b83cSArmin Le Grand SalBitmap* pSalSrcBmp = rBitmapEx.GetBitmap().ImplGetImpBitmap()->ImplGetSalBitmap(); 8555f27b83cSArmin Le Grand SalBitmap* pSalAlphaBmp = 0; 8565f27b83cSArmin Le Grand 8575f27b83cSArmin Le Grand if(rBitmapEx.IsTransparent()) 8585f27b83cSArmin Le Grand { 8595f27b83cSArmin Le Grand if(rBitmapEx.IsAlpha()) 8605f27b83cSArmin Le Grand { 8615f27b83cSArmin Le Grand pSalAlphaBmp = rBitmapEx.GetAlpha().ImplGetImpBitmap()->ImplGetSalBitmap(); 8625f27b83cSArmin Le Grand } 8635f27b83cSArmin Le Grand else 8645f27b83cSArmin Le Grand { 8655f27b83cSArmin Le Grand pSalAlphaBmp = rBitmapEx.GetMask().ImplGetImpBitmap()->ImplGetSalBitmap(); 8665f27b83cSArmin Le Grand } 8675f27b83cSArmin Le Grand } 8685f27b83cSArmin Le Grand 8695f27b83cSArmin Le Grand bDone = mpGraphics->DrawTransformedBitmap( 8705f27b83cSArmin Le Grand aNull, 8715f27b83cSArmin Le Grand aTopX, 8725f27b83cSArmin Le Grand aTopY, 8735f27b83cSArmin Le Grand *pSalSrcBmp, 8745f27b83cSArmin Le Grand pSalAlphaBmp, 8755f27b83cSArmin Le Grand this); 8765f27b83cSArmin Le Grand } 8775f27b83cSArmin Le Grand 8785f27b83cSArmin Le Grand if(!bDone) 8795f27b83cSArmin Le Grand { 8805f27b83cSArmin Le Grand // take the fallback when no rotate and shear, but mirror (else we would have done this above) 881f8c0d554SArmin Le Grand if(!bForceToOwnTransformer && !bRotated && !bSheared) 8825f27b83cSArmin Le Grand { 8835f27b83cSArmin Le Grand // with no rotation or shear it can be mapped to DrawBitmapEx 8845f27b83cSArmin Le Grand // do *not* execute the mirroring here, it's done in the fallback 885fa004bb0SArmin Le Grand // #124580# the correct DestSize needs to be calculated based on MaxXY values 8865f27b83cSArmin Le Grand const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY())); 887fa004bb0SArmin Le Grand const Size aDestSize( 888fa004bb0SArmin Le Grand basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(), 889fa004bb0SArmin Le Grand basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y()); 8905f27b83cSArmin Le Grand 8915f27b83cSArmin Le Grand DrawBitmapEx(aDestPt, aDestSize, rBitmapEx); 8925f27b83cSArmin Le Grand return; 8935f27b83cSArmin Le Grand } 8945f27b83cSArmin Le Grand 8955f27b83cSArmin Le Grand // fallback; create transformed bitmap the hard way (back-transform 8965f27b83cSArmin Le Grand // the pixels) and paint 897f8c0d554SArmin Le Grand basegfx::B2DRange aVisibleRange(0.0, 0.0, 1.0, 1.0); 898f8c0d554SArmin Le Grand 899f8c0d554SArmin Le Grand // limit maximum area to something looking good for non-pixel-based targets (metafile, printer) 9005496114cSArmin Le Grand // by using a fixed minimum (allow at least, but no need to utilize) for good smooting and an area 9015496114cSArmin Le Grand // dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum 9020000282aSJohn Bampton // to avoid crashes/resource problems (ca. 1500x3000 here) 9035496114cSArmin Le Grand const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel()); 9045496114cSArmin Le Grand const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5); 9055496114cSArmin Le Grand const double fOrigAreaScaled(bSheared || bRotated ? fOrigArea * 1.44 : fOrigArea); 9065496114cSArmin Le Grand double fMaximumArea(std::min(4500000.0, std::max(1000000.0, fOrigAreaScaled))); 907f8c0d554SArmin Le Grand 908f8c0d554SArmin Le Grand if(!bMetafile && !bPrinter) 909f8c0d554SArmin Le Grand { 910f8c0d554SArmin Le Grand // limit TargetRange to existing pixels (if pixel device) 911f8c0d554SArmin Le Grand // first get discrete range of object 912f8c0d554SArmin Le Grand basegfx::B2DRange aFullPixelRange(aVisibleRange); 913f8c0d554SArmin Le Grand 914f8c0d554SArmin Le Grand aFullPixelRange.transform(aFullTransform); 915f8c0d554SArmin Le Grand 916f8c0d554SArmin Le Grand if(basegfx::fTools::equalZero(aFullPixelRange.getWidth()) || basegfx::fTools::equalZero(aFullPixelRange.getHeight())) 917f8c0d554SArmin Le Grand { 918f8c0d554SArmin Le Grand // object is outside of visible area 919f8c0d554SArmin Le Grand return; 920f8c0d554SArmin Le Grand } 921f8c0d554SArmin Le Grand 922f8c0d554SArmin Le Grand // now get discrete target pixels; start with OutDev pixel size and evtl. 923f8c0d554SArmin Le Grand // intersect with active clipping area 924f8c0d554SArmin Le Grand basegfx::B2DRange aOutPixel( 925f8c0d554SArmin Le Grand 0.0, 926f8c0d554SArmin Le Grand 0.0, 927f8c0d554SArmin Le Grand GetOutputSizePixel().Width(), 928f8c0d554SArmin Le Grand GetOutputSizePixel().Height()); 929f8c0d554SArmin Le Grand 930f8c0d554SArmin Le Grand if(IsClipRegion()) 931f8c0d554SArmin Le Grand { 932f8c0d554SArmin Le Grand const Rectangle aRegionRectangle(GetActiveClipRegion().GetBoundRect()); 933f8c0d554SArmin Le Grand 934f8c0d554SArmin Le Grand aOutPixel.intersect( // caution! Range from rectangle, one too much (!) 935f8c0d554SArmin Le Grand basegfx::B2DRange( 936f8c0d554SArmin Le Grand aRegionRectangle.Left(), 937f8c0d554SArmin Le Grand aRegionRectangle.Top(), 938f8c0d554SArmin Le Grand aRegionRectangle.Right() + 1, 939f8c0d554SArmin Le Grand aRegionRectangle.Bottom() + 1)); 940f8c0d554SArmin Le Grand } 941f8c0d554SArmin Le Grand 942f8c0d554SArmin Le Grand if(aOutPixel.isEmpty()) 943f8c0d554SArmin Le Grand { 944f8c0d554SArmin Le Grand // no active output area 945f8c0d554SArmin Le Grand return; 946f8c0d554SArmin Le Grand } 947f8c0d554SArmin Le Grand 948f8c0d554SArmin Le Grand // if aFullPixelRange is not completely inside of aOutPixel, 949f8c0d554SArmin Le Grand // reduction of target pixels is possible 950f8c0d554SArmin Le Grand basegfx::B2DRange aVisiblePixelRange(aFullPixelRange); 951f8c0d554SArmin Le Grand 952f8c0d554SArmin Le Grand if(!aOutPixel.isInside(aFullPixelRange)) 953f8c0d554SArmin Le Grand { 954f8c0d554SArmin Le Grand aVisiblePixelRange.intersect(aOutPixel); 955f8c0d554SArmin Le Grand 956f8c0d554SArmin Le Grand if(aVisiblePixelRange.isEmpty()) 957f8c0d554SArmin Le Grand { 958f8c0d554SArmin Le Grand // nothing in visible part, reduces to nothing 959f8c0d554SArmin Le Grand return; 960f8c0d554SArmin Le Grand } 961f8c0d554SArmin Le Grand 962f8c0d554SArmin Le Grand // aVisiblePixelRange contains the reduced output area in 963f8c0d554SArmin Le Grand // discrete coordinates. To make it useful everywhere, make it relative to 964f8c0d554SArmin Le Grand // the object range 965f8c0d554SArmin Le Grand basegfx::B2DHomMatrix aMakeVisibleRangeRelative; 966f8c0d554SArmin Le Grand 967f8c0d554SArmin Le Grand aVisibleRange = aVisiblePixelRange; 968f8c0d554SArmin Le Grand aMakeVisibleRangeRelative.translate( 969f8c0d554SArmin Le Grand -aFullPixelRange.getMinX(), 970f8c0d554SArmin Le Grand -aFullPixelRange.getMinY()); 971f8c0d554SArmin Le Grand aMakeVisibleRangeRelative.scale( 972f8c0d554SArmin Le Grand 1.0 / aFullPixelRange.getWidth(), 973f8c0d554SArmin Le Grand 1.0 / aFullPixelRange.getHeight()); 974f8c0d554SArmin Le Grand aVisibleRange.transform(aMakeVisibleRangeRelative); 975f8c0d554SArmin Le Grand } 976f8c0d554SArmin Le Grand 977f8c0d554SArmin Le Grand // for pixel devices, do *not* limit size, else OutputDevice::ImplDrawAlpha 978f8c0d554SArmin Le Grand // will create another, badly scaled bitmap to do the job. Nonetheless, do a 979f8c0d554SArmin Le Grand // maximum clipping of something big (1600x1280x2). Add 1.0 to avoid rounding 980f8c0d554SArmin Le Grand // errors in rough estimations 981f8c0d554SArmin Le Grand const double fNewMaxArea(aVisiblePixelRange.getWidth() * aVisiblePixelRange.getHeight()); 982f8c0d554SArmin Le Grand 983f8c0d554SArmin Le Grand fMaximumArea = std::min(4096000.0, fNewMaxArea + 1.0); 984f8c0d554SArmin Le Grand } 985f8c0d554SArmin Le Grand 986f8c0d554SArmin Le Grand if(!aVisibleRange.isEmpty()) 987f8c0d554SArmin Le Grand { 988f8c0d554SArmin Le Grand static bool bDoSmoothAtAll(true); 9895496114cSArmin Le Grand BitmapEx aTransformed(rBitmapEx); 9905496114cSArmin Le Grand 9915496114cSArmin Le Grand // #122923# when the result needs an alpha channel due to being rotated or sheared 9925496114cSArmin Le Grand // and thus uncovering areas, add these channels so that the own transformer (used 9935496114cSArmin Le Grand // in getTransformed) also creates a transformed alpha channel 9945496114cSArmin Le Grand if(!aTransformed.IsTransparent() && (bSheared || bRotated)) 9955496114cSArmin Le Grand { 9965496114cSArmin Le Grand // parts will be uncovered, extend aTransformed with a mask bitmap 9975496114cSArmin Le Grand const Bitmap aContent(aTransformed.GetBitmap()); 9985496114cSArmin Le Grand #if defined(MACOSX) 9995496114cSArmin Le Grand AlphaMask aMaskBmp(aContent.GetSizePixel()); 10005496114cSArmin Le Grand aMaskBmp.Erase(0); 10015496114cSArmin Le Grand #else 10025496114cSArmin Le Grand Bitmap aMaskBmp(aContent.GetSizePixel(), 1); 10035496114cSArmin Le Grand aMaskBmp.Erase(Color(COL_BLACK)); // #122758# Initialize to non-transparent 10045496114cSArmin Le Grand #endif 10055496114cSArmin Le Grand aTransformed = BitmapEx(aContent, aMaskBmp); 10065496114cSArmin Le Grand } 10075496114cSArmin Le Grand 10085496114cSArmin Le Grand aTransformed = aTransformed.getTransformed( 1009f8c0d554SArmin Le Grand aFullTransform, 1010f8c0d554SArmin Le Grand aVisibleRange, 1011f8c0d554SArmin Le Grand fMaximumArea, 10125496114cSArmin Le Grand bDoSmoothAtAll); 10135f27b83cSArmin Le Grand basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0); 1014f8c0d554SArmin Le Grand 1015f8c0d554SArmin Le Grand // get logic object target range 10165f27b83cSArmin Le Grand aTargetRange.transform(rTransformation); 1017f8c0d554SArmin Le Grand 1018f8c0d554SArmin Le Grand // get from unified/relative VisibleRange to logoc one 1019f8c0d554SArmin Le Grand aVisibleRange.transform( 1020f8c0d554SArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 1021f8c0d554SArmin Le Grand aTargetRange.getRange(), 1022f8c0d554SArmin Le Grand aTargetRange.getMinimum())); 1023f8c0d554SArmin Le Grand 1024f8c0d554SArmin Le Grand // extract point and size; do not remove size, the bitmap may have been prepared reduced by purpose 1025fa004bb0SArmin Le Grand // #124580# the correct DestSize needs to be calculated based on MaxXY values 1026f8c0d554SArmin Le Grand const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY())); 1027fa004bb0SArmin Le Grand const Size aDestSize( 1028fa004bb0SArmin Le Grand basegfx::fround(aVisibleRange.getMaxX()) - aDestPt.X(), 1029fa004bb0SArmin Le Grand basegfx::fround(aVisibleRange.getMaxY()) - aDestPt.Y()); 10305f27b83cSArmin Le Grand 10315f27b83cSArmin Le Grand DrawBitmapEx(aDestPt, aDestSize, aTransformed); 10325f27b83cSArmin Le Grand } 10335f27b83cSArmin Le Grand } 1034f8c0d554SArmin Le Grand } 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir // ------------------------------------------------------------------ 1037cdf0e10cSrcweir 1038cdf0e10cSrcweir void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize, 1039cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 1040cdf0e10cSrcweir const BitmapEx& rBitmapEx, const sal_uLong nAction ) 1041cdf0e10cSrcweir { 1042cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 10435f27b83cSArmin Le Grand OSL_ENSURE(TRANSPARENT_NONE != rBitmapEx.GetTransparentType(), "ImplDrawBitmapEx not needed, no transparency in BitmapEx (!)"); 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_NOBITMAP ) 1046cdf0e10cSrcweir return; 10475f27b83cSArmin Le Grand 10485f27b83cSArmin Le Grand if ( ROP_INVERT == meRasterOp ) 1049cdf0e10cSrcweir { 1050cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 1051cdf0e10cSrcweir return; 1052cdf0e10cSrcweir } 10535f27b83cSArmin Le Grand 10545f27b83cSArmin Le Grand BitmapEx aBmpEx( rBitmapEx ); 10555f27b83cSArmin Le Grand 10565f27b83cSArmin Le Grand if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | 1057cdf0e10cSrcweir DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) ) 1058cdf0e10cSrcweir { 1059cdf0e10cSrcweir if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) ) 1060cdf0e10cSrcweir { 1061cdf0e10cSrcweir Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 ); 1062cdf0e10cSrcweir sal_uInt8 cCmpVal; 1063cdf0e10cSrcweir 1064cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_BLACKBITMAP ) 1065cdf0e10cSrcweir cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0; 1066cdf0e10cSrcweir else 1067cdf0e10cSrcweir cCmpVal = 255; 1068cdf0e10cSrcweir 1069cdf0e10cSrcweir aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) ); 1070cdf0e10cSrcweir 1071cdf0e10cSrcweir if( aBmpEx.IsAlpha() ) 1072cdf0e10cSrcweir { 1073cdf0e10cSrcweir // Create one-bit mask out of alpha channel, by 1074cdf0e10cSrcweir // thresholding it at alpha=0.5. As 1075cdf0e10cSrcweir // DRAWMODE_BLACK/WHITEBITMAP requires monochrome 1076cdf0e10cSrcweir // output, having alpha-induced grey levels is not 1077cdf0e10cSrcweir // acceptable. 1078cdf0e10cSrcweir Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() ); 1079cdf0e10cSrcweir aMask.MakeMono( 128 ); 1080cdf0e10cSrcweir aBmpEx = BitmapEx( aColorBmp, aMask ); 1081cdf0e10cSrcweir } 1082cdf0e10cSrcweir else 1083cdf0e10cSrcweir { 1084cdf0e10cSrcweir aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() ); 1085cdf0e10cSrcweir } 1086cdf0e10cSrcweir } 1087cdf0e10cSrcweir else if( !!aBmpEx ) 1088cdf0e10cSrcweir { 1089cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GRAYBITMAP ) 1090cdf0e10cSrcweir aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS ); 1091cdf0e10cSrcweir 1092cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) 1093cdf0e10cSrcweir aBmpEx.Convert( BMP_CONVERSION_GHOSTED ); 1094cdf0e10cSrcweir } 1095cdf0e10cSrcweir } 1096cdf0e10cSrcweir 1097cdf0e10cSrcweir if ( mpMetaFile ) 1098cdf0e10cSrcweir { 1099cdf0e10cSrcweir switch( nAction ) 1100cdf0e10cSrcweir { 1101cdf0e10cSrcweir case( META_BMPEX_ACTION ): 1102cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) ); 1103cdf0e10cSrcweir break; 1104cdf0e10cSrcweir 1105cdf0e10cSrcweir case( META_BMPEXSCALE_ACTION ): 1106cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) ); 1107cdf0e10cSrcweir break; 1108cdf0e10cSrcweir 1109cdf0e10cSrcweir case( META_BMPEXSCALEPART_ACTION ): 1110cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize, 1111cdf0e10cSrcweir rSrcPtPixel, rSrcSizePixel, aBmpEx ) ); 1112cdf0e10cSrcweir break; 1113cdf0e10cSrcweir } 1114cdf0e10cSrcweir } 1115cdf0e10cSrcweir 1116cdf0e10cSrcweir OUTDEV_INIT(); 1117cdf0e10cSrcweir 1118cdf0e10cSrcweir if( OUTDEV_PRINTER == meOutDevType ) 1119cdf0e10cSrcweir { 1120cdf0e10cSrcweir if( aBmpEx.IsAlpha() ) 1121cdf0e10cSrcweir { 1122cdf0e10cSrcweir // #107169# For true alpha bitmaps, no longer masking the 1123cdf0e10cSrcweir // bitmap, but perform a full alpha blend against a white 1124cdf0e10cSrcweir // background here. 1125cdf0e10cSrcweir Bitmap aBmp( aBmpEx.GetBitmap() ); 1126cdf0e10cSrcweir aBmp.Blend( aBmpEx.GetAlpha(), Color( COL_WHITE) ); 1127cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ); 1128cdf0e10cSrcweir } 1129cdf0e10cSrcweir else 1130cdf0e10cSrcweir { 1131cdf0e10cSrcweir Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() ); 1132cdf0e10cSrcweir aBmp.Replace( aMask, Color( COL_WHITE ) ); 1133cdf0e10cSrcweir ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel ); 1134cdf0e10cSrcweir } 11355f27b83cSArmin Le Grand 1136cdf0e10cSrcweir return; 1137cdf0e10cSrcweir } 11385f27b83cSArmin Le Grand 11395f27b83cSArmin Le Grand if(aBmpEx.IsAlpha()) 1140cdf0e10cSrcweir { 1141cdf0e10cSrcweir ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel ); 1142cdf0e10cSrcweir return; 1143cdf0e10cSrcweir } 1144cdf0e10cSrcweir 1145cdf0e10cSrcweir if( !( !aBmpEx ) ) 1146cdf0e10cSrcweir { 11475f27b83cSArmin Le Grand SalTwoRect aPosAry; 1148cdf0e10cSrcweir 1149cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X(); 1150cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y(); 1151cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width(); 1152cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height(); 1153cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 1154cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 1155cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 1156cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 1157cdf0e10cSrcweir 1158cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() ); 1159cdf0e10cSrcweir 1160cdf0e10cSrcweir if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 1161cdf0e10cSrcweir { 1162cdf0e10cSrcweir 1163cdf0e10cSrcweir if( nMirrFlags ) 1164cdf0e10cSrcweir aBmpEx.Mirror( nMirrFlags ); 1165cdf0e10cSrcweir 11665f27b83cSArmin Le Grand const SalBitmap* pSalSrcBmp = aBmpEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap(); 1167cdf0e10cSrcweir const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap(); 1168cdf0e10cSrcweir 1169cdf0e10cSrcweir if ( pMaskBmp ) 1170cdf0e10cSrcweir { 11715f27b83cSArmin Le Grand SalBitmap* pSalAlphaBmp = pMaskBmp->ImplGetSalBitmap(); 11725f27b83cSArmin Le Grand bool bTryDirectPaint(pSalSrcBmp && pSalAlphaBmp); 11735f27b83cSArmin Le Grand 11745f27b83cSArmin Le Grand if(bTryDirectPaint) 11755f27b83cSArmin Le Grand { 11765f27b83cSArmin Le Grand // only paint direct when no scaling and no MapMode, else the 11775f27b83cSArmin Le Grand // more expensive conversions may be done for short-time Bitmap/BitmapEx 11785f27b83cSArmin Le Grand // used for buffering only 11795f27b83cSArmin Le Grand if(!IsMapMode() && aPosAry.mnSrcWidth == aPosAry.mnDestWidth && aPosAry.mnSrcHeight == aPosAry.mnDestHeight) 11805f27b83cSArmin Le Grand { 11815f27b83cSArmin Le Grand bTryDirectPaint = false; 11825f27b83cSArmin Le Grand } 11835f27b83cSArmin Le Grand } 11845f27b83cSArmin Le Grand 11855f27b83cSArmin Le Grand if(bTryDirectPaint && mpGraphics->DrawAlphaBitmap(aPosAry, *pSalSrcBmp, *pSalAlphaBmp, this)) 11865f27b83cSArmin Le Grand { 11875f27b83cSArmin Le Grand // tried to paint as alpha directly. If tis worked, we are done (except 11885f27b83cSArmin Le Grand // alpha, see below) 11895f27b83cSArmin Le Grand } 11905f27b83cSArmin Le Grand else 11915f27b83cSArmin Le Grand { 1192cdf0e10cSrcweir // #4919452# reduce operation area to bounds of 1193cdf0e10cSrcweir // cliprect. since masked transparency involves 1194cdf0e10cSrcweir // creation of a large vdev and copying the screen 1195cdf0e10cSrcweir // content into that (slooow read from framebuffer), 1196cdf0e10cSrcweir // that should considerably increase performance for 1197cdf0e10cSrcweir // large bitmaps and small clippings. 1198cdf0e10cSrcweir 1199cdf0e10cSrcweir // Note that this optimisation is a workaround for a 1200cdf0e10cSrcweir // Writer peculiarity, namely, to decompose background 1201cdf0e10cSrcweir // graphics into myriads of disjunct, tiny 1202cdf0e10cSrcweir // rectangles. That otherwise kills us here, since for 1203cdf0e10cSrcweir // transparent output, SAL always prepares the whole 1204cdf0e10cSrcweir // bitmap, if aPosAry contains the whole bitmap (and 1205cdf0e10cSrcweir // it's _not_ to blame for that). 1206cdf0e10cSrcweir 1207cdf0e10cSrcweir // Note the call to ImplPixelToDevicePixel(), since 1208cdf0e10cSrcweir // aPosAry already contains the mnOutOff-offsets, they 1209cdf0e10cSrcweir // also have to be applied to the region 1210cdf0e10cSrcweir Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() ); 1211cdf0e10cSrcweir 1212cdf0e10cSrcweir // TODO: Also respect scaling (that's a bit tricky, 1213cdf0e10cSrcweir // since the source points have to move fractional 1214cdf0e10cSrcweir // amounts (which is not possible, thus has to be 1215cdf0e10cSrcweir // emulated by increases copy area) 1216cdf0e10cSrcweir // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth ); 1217cdf0e10cSrcweir // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight ); 1218cdf0e10cSrcweir 1219cdf0e10cSrcweir // for now, only identity scales allowed 1220cdf0e10cSrcweir if( !aClipRegionBounds.IsEmpty() && 1221cdf0e10cSrcweir aPosAry.mnDestWidth == aPosAry.mnSrcWidth && 1222cdf0e10cSrcweir aPosAry.mnDestHeight == aPosAry.mnSrcHeight ) 1223cdf0e10cSrcweir { 1224cdf0e10cSrcweir // now intersect dest rect with clip region 1225cdf0e10cSrcweir aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX, 1226cdf0e10cSrcweir aPosAry.mnDestY, 1227cdf0e10cSrcweir aPosAry.mnDestX + aPosAry.mnDestWidth - 1, 1228cdf0e10cSrcweir aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) ); 1229cdf0e10cSrcweir 1230cdf0e10cSrcweir // Note: I could theoretically optimize away the 1231cdf0e10cSrcweir // DrawBitmap below, if the region is empty 1232cdf0e10cSrcweir // here. Unfortunately, cannot rule out that 1233cdf0e10cSrcweir // somebody relies on the side effects. 1234cdf0e10cSrcweir if( !aClipRegionBounds.IsEmpty() ) 1235cdf0e10cSrcweir { 1236cdf0e10cSrcweir aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX; 1237cdf0e10cSrcweir aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY; 1238cdf0e10cSrcweir aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth(); 1239cdf0e10cSrcweir aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight(); 1240cdf0e10cSrcweir 1241cdf0e10cSrcweir aPosAry.mnDestX = aClipRegionBounds.Left(); 1242cdf0e10cSrcweir aPosAry.mnDestY = aClipRegionBounds.Top(); 1243cdf0e10cSrcweir aPosAry.mnDestWidth = aClipRegionBounds.GetWidth(); 1244cdf0e10cSrcweir aPosAry.mnDestHeight = aClipRegionBounds.GetHeight(); 1245cdf0e10cSrcweir } 1246cdf0e10cSrcweir } 1247cdf0e10cSrcweir 12485f27b83cSArmin Le Grand mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp, 1249cdf0e10cSrcweir *pMaskBmp->ImplGetSalBitmap(), 1250cdf0e10cSrcweir this ); 12515f27b83cSArmin Le Grand } 1252cdf0e10cSrcweir 1253cdf0e10cSrcweir // #110958# Paint mask to alpha channel. Luckily, the 1254cdf0e10cSrcweir // black and white representation of the mask maps to 1255cdf0e10cSrcweir // the alpha channel 1256cdf0e10cSrcweir 1257cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1258cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1259cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1260cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1261cdf0e10cSrcweir // the transparency mask of itself 1262cdf0e10cSrcweir if( mpAlphaVDev ) 1263cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1264cdf0e10cSrcweir rDestSize, 1265cdf0e10cSrcweir BitmapEx( aBmpEx.GetMask(), 1266cdf0e10cSrcweir aBmpEx.GetMask() ) ); 1267cdf0e10cSrcweir } 1268cdf0e10cSrcweir else 1269cdf0e10cSrcweir { 12705f27b83cSArmin Le Grand mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp, this ); 1271cdf0e10cSrcweir 1272cdf0e10cSrcweir if( mpAlphaVDev ) 1273cdf0e10cSrcweir { 1274cdf0e10cSrcweir // #i32109#: Make bitmap area opaque 1275cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) ); 1276cdf0e10cSrcweir } 1277cdf0e10cSrcweir } 1278cdf0e10cSrcweir } 1279cdf0e10cSrcweir } 1280cdf0e10cSrcweir } 1281cdf0e10cSrcweir 1282cdf0e10cSrcweir // ------------------------------------------------------------------ 1283cdf0e10cSrcweir 1284cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, 1285cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor ) 1286cdf0e10cSrcweir { 1287cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask()" ); 1288cdf0e10cSrcweir 1289cdf0e10cSrcweir if( ImplIsRecordLayout() ) 1290cdf0e10cSrcweir return; 1291cdf0e10cSrcweir 1292cdf0e10cSrcweir const Size aSizePix( rBitmap.GetSizePixel() ); 1293cdf0e10cSrcweir ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION ); 1294cdf0e10cSrcweir 1295cdf0e10cSrcweir if( mpAlphaVDev ) 1296cdf0e10cSrcweir { 1297cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) ); 1298cdf0e10cSrcweir 1299cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1300cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1301cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1302cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1303cdf0e10cSrcweir // the transparency mask of itself 1304cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1305cdf0e10cSrcweir PixelToLogic( aSizePix ), 1306cdf0e10cSrcweir BitmapEx( rMask, rMask ) ); 1307cdf0e10cSrcweir } 1308cdf0e10cSrcweir } 1309cdf0e10cSrcweir 1310cdf0e10cSrcweir // ------------------------------------------------------------------ 1311cdf0e10cSrcweir 1312cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize, 1313cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor ) 1314cdf0e10cSrcweir { 1315cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask( Size )" ); 1316cdf0e10cSrcweir 1317cdf0e10cSrcweir if( ImplIsRecordLayout() ) 1318cdf0e10cSrcweir return; 1319cdf0e10cSrcweir 1320cdf0e10cSrcweir ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION ); 1321cdf0e10cSrcweir 1322cdf0e10cSrcweir // TODO: Use mask here 1323cdf0e10cSrcweir if( mpAlphaVDev ) 1324cdf0e10cSrcweir { 1325cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) ); 1326cdf0e10cSrcweir 1327cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1328cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1329cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1330cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1331cdf0e10cSrcweir // the transparency mask of itself 1332cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1333cdf0e10cSrcweir rDestSize, 1334cdf0e10cSrcweir BitmapEx( rMask, rMask ) ); 1335cdf0e10cSrcweir } 1336cdf0e10cSrcweir } 1337cdf0e10cSrcweir 1338cdf0e10cSrcweir // ------------------------------------------------------------------ 1339cdf0e10cSrcweir 1340cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize, 1341cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 1342cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor ) 1343cdf0e10cSrcweir { 1344cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" ); 1345cdf0e10cSrcweir 1346cdf0e10cSrcweir if( ImplIsRecordLayout() ) 1347cdf0e10cSrcweir return; 1348cdf0e10cSrcweir 1349cdf0e10cSrcweir ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION ); 1350cdf0e10cSrcweir 1351cdf0e10cSrcweir // TODO: Use mask here 1352cdf0e10cSrcweir if( mpAlphaVDev ) 1353cdf0e10cSrcweir { 1354cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) ); 1355cdf0e10cSrcweir 1356cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas 1357cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no 1358cdf0e10cSrcweir // bitmap content was ever visible. Interestingly 1359cdf0e10cSrcweir // enough, this can be achieved by taking the mask as 1360cdf0e10cSrcweir // the transparency mask of itself 1361cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt, 1362cdf0e10cSrcweir rDestSize, 1363cdf0e10cSrcweir rSrcPtPixel, 1364cdf0e10cSrcweir rSrcSizePixel, 1365cdf0e10cSrcweir BitmapEx( rMask, rMask ) ); 1366cdf0e10cSrcweir } 1367cdf0e10cSrcweir } 1368cdf0e10cSrcweir 1369cdf0e10cSrcweir // ------------------------------------------------------------------ 1370cdf0e10cSrcweir 1371cdf0e10cSrcweir void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize, 1372cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel, 1373cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor, 1374cdf0e10cSrcweir const sal_uLong nAction ) 1375cdf0e10cSrcweir { 1376cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1377cdf0e10cSrcweir 1378cdf0e10cSrcweir if( ROP_INVERT == meRasterOp ) 1379cdf0e10cSrcweir { 1380cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) ); 1381cdf0e10cSrcweir return; 1382cdf0e10cSrcweir } 1383cdf0e10cSrcweir 1384cdf0e10cSrcweir if ( mpMetaFile ) 1385cdf0e10cSrcweir { 1386cdf0e10cSrcweir switch( nAction ) 1387cdf0e10cSrcweir { 1388cdf0e10cSrcweir case( META_MASK_ACTION ): 1389cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskAction( rDestPt, 1390cdf0e10cSrcweir rBitmap, rMaskColor ) ); 1391cdf0e10cSrcweir break; 1392cdf0e10cSrcweir 1393cdf0e10cSrcweir case( META_MASKSCALE_ACTION ): 1394cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt, 1395cdf0e10cSrcweir rDestSize, rBitmap, rMaskColor ) ); 1396cdf0e10cSrcweir break; 1397cdf0e10cSrcweir 1398cdf0e10cSrcweir case( META_MASKSCALEPART_ACTION ): 1399cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize, 1400cdf0e10cSrcweir rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) ); 1401cdf0e10cSrcweir break; 1402cdf0e10cSrcweir } 1403cdf0e10cSrcweir } 1404cdf0e10cSrcweir 1405cdf0e10cSrcweir OUTDEV_INIT(); 1406cdf0e10cSrcweir 1407cdf0e10cSrcweir if ( OUTDEV_PRINTER == meOutDevType ) 1408cdf0e10cSrcweir { 1409cdf0e10cSrcweir ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel ); 1410cdf0e10cSrcweir return; 1411cdf0e10cSrcweir } 1412cdf0e10cSrcweir 1413cdf0e10cSrcweir const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap(); 1414cdf0e10cSrcweir if ( pImpBmp ) 1415cdf0e10cSrcweir { 14165f27b83cSArmin Le Grand SalTwoRect aPosAry; 1417cdf0e10cSrcweir 1418cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X(); 1419cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y(); 1420cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width(); 1421cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height(); 1422cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() ); 1423cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() ); 1424cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() ); 1425cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() ); 1426cdf0e10cSrcweir 1427cdf0e10cSrcweir // spiegeln via Koordinaten wollen wir nicht 1428cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() ); 1429cdf0e10cSrcweir 1430cdf0e10cSrcweir // check if output is necessary 1431cdf0e10cSrcweir if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight ) 1432cdf0e10cSrcweir { 1433cdf0e10cSrcweir 1434cdf0e10cSrcweir if( nMirrFlags ) 1435cdf0e10cSrcweir { 1436cdf0e10cSrcweir Bitmap aTmp( rBitmap ); 1437cdf0e10cSrcweir aTmp.Mirror( nMirrFlags ); 14385f27b83cSArmin Le Grand mpGraphics->DrawMask( aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(), 1439cdf0e10cSrcweir ImplColorToSal( rMaskColor ) , this); 1440cdf0e10cSrcweir } 1441cdf0e10cSrcweir else 14425f27b83cSArmin Le Grand mpGraphics->DrawMask( aPosAry, *pImpBmp->ImplGetSalBitmap(), 1443cdf0e10cSrcweir ImplColorToSal( rMaskColor ), this ); 1444cdf0e10cSrcweir 1445cdf0e10cSrcweir } 1446cdf0e10cSrcweir } 1447cdf0e10cSrcweir } 1448cdf0e10cSrcweir 1449cdf0e10cSrcweir // ------------------------------------------------------------------ 1450cdf0e10cSrcweir 1451cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle ) 1452cdf0e10cSrcweir { 1453cdf0e10cSrcweir DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" ); 1454cdf0e10cSrcweir 1455cdf0e10cSrcweir if( !rImage.mpImplData || ImplIsRecordLayout() ) 1456cdf0e10cSrcweir return; 1457cdf0e10cSrcweir 1458cdf0e10cSrcweir switch( rImage.mpImplData->meType ) 1459cdf0e10cSrcweir { 1460cdf0e10cSrcweir case IMAGETYPE_BITMAP: 1461cdf0e10cSrcweir DrawBitmap( rPos, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) ); 1462cdf0e10cSrcweir break; 1463cdf0e10cSrcweir 1464cdf0e10cSrcweir case IMAGETYPE_IMAGE: 1465cdf0e10cSrcweir { 1466cdf0e10cSrcweir ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData ); 1467cdf0e10cSrcweir 1468cdf0e10cSrcweir if( !pData->mpImageBitmap ) 1469cdf0e10cSrcweir { 1470cdf0e10cSrcweir const Size aSize( pData->maBmpEx.GetSizePixel() ); 1471cdf0e10cSrcweir 1472cdf0e10cSrcweir pData->mpImageBitmap = new ImplImageBmp; 1473cdf0e10cSrcweir pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 ); 1474cdf0e10cSrcweir } 1475cdf0e10cSrcweir 1476cdf0e10cSrcweir pData->mpImageBitmap->Draw( 0, this, rPos, nStyle ); 1477cdf0e10cSrcweir } 1478cdf0e10cSrcweir break; 1479cdf0e10cSrcweir 1480cdf0e10cSrcweir default: 1481cdf0e10cSrcweir break; 1482cdf0e10cSrcweir } 1483cdf0e10cSrcweir } 1484cdf0e10cSrcweir 1485cdf0e10cSrcweir // ------------------------------------------------------------------ 1486cdf0e10cSrcweir 1487cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Size& rSize, 1488cdf0e10cSrcweir const Image& rImage, sal_uInt16 nStyle ) 1489cdf0e10cSrcweir { 1490cdf0e10cSrcweir DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" ); 1491cdf0e10cSrcweir 1492cdf0e10cSrcweir if( rImage.mpImplData && !ImplIsRecordLayout() ) 1493cdf0e10cSrcweir { 1494cdf0e10cSrcweir switch( rImage.mpImplData->meType ) 1495cdf0e10cSrcweir { 1496cdf0e10cSrcweir case IMAGETYPE_BITMAP: 1497cdf0e10cSrcweir DrawBitmap( rPos, rSize, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) ); 1498cdf0e10cSrcweir break; 1499cdf0e10cSrcweir 1500cdf0e10cSrcweir case IMAGETYPE_IMAGE: 1501cdf0e10cSrcweir { 1502cdf0e10cSrcweir ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData ); 1503cdf0e10cSrcweir 1504cdf0e10cSrcweir if ( !pData->mpImageBitmap ) 1505cdf0e10cSrcweir { 1506cdf0e10cSrcweir const Size aSize( pData->maBmpEx.GetSizePixel() ); 1507cdf0e10cSrcweir 1508cdf0e10cSrcweir pData->mpImageBitmap = new ImplImageBmp; 1509cdf0e10cSrcweir pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 ); 1510cdf0e10cSrcweir } 1511cdf0e10cSrcweir 1512cdf0e10cSrcweir pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize ); 1513cdf0e10cSrcweir } 1514cdf0e10cSrcweir break; 1515cdf0e10cSrcweir 1516cdf0e10cSrcweir default: 1517cdf0e10cSrcweir break; 1518cdf0e10cSrcweir } 1519cdf0e10cSrcweir } 1520cdf0e10cSrcweir } 1521cdf0e10cSrcweir 1522cdf0e10cSrcweir // ------------------------------------------------------------------ 1523cdf0e10cSrcweir 1524cdf0e10cSrcweir Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const 1525cdf0e10cSrcweir { 1526cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1527*674f8708SJohn Bampton OSL_ENSURE(OUTDEV_PRINTER != GetOutDevType(), "OutputDevice::GetBitmap with source type OUTDEV_PRINTER should not be used (!)"); 1528cdf0e10cSrcweir 1529cdf0e10cSrcweir Bitmap aBmp; 1530cdf0e10cSrcweir long nX = ImplLogicXToDevicePixel( rSrcPt.X() ); 1531cdf0e10cSrcweir long nY = ImplLogicYToDevicePixel( rSrcPt.Y() ); 1532cdf0e10cSrcweir long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() ); 1533cdf0e10cSrcweir long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() ); 1534cdf0e10cSrcweir 1535cdf0e10cSrcweir if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() ) 1536cdf0e10cSrcweir { 1537ff0f521cSArmin Le Grand if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY)) 1538cdf0e10cSrcweir { 1539cdf0e10cSrcweir Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) ); 1540cdf0e10cSrcweir sal_Bool bClipped = sal_False; 1541cdf0e10cSrcweir 1542cdf0e10cSrcweir // X-Koordinate ausserhalb des Bereichs? 1543cdf0e10cSrcweir if ( nX < mnOutOffX ) 1544cdf0e10cSrcweir { 1545cdf0e10cSrcweir nWidth -= ( mnOutOffX - nX ); 1546cdf0e10cSrcweir nX = mnOutOffX; 1547cdf0e10cSrcweir bClipped = sal_True; 1548cdf0e10cSrcweir } 1549cdf0e10cSrcweir 1550cdf0e10cSrcweir // Y-Koordinate ausserhalb des Bereichs? 1551cdf0e10cSrcweir if ( nY < mnOutOffY ) 1552cdf0e10cSrcweir { 1553cdf0e10cSrcweir nHeight -= ( mnOutOffY - nY ); 1554cdf0e10cSrcweir nY = mnOutOffY; 1555cdf0e10cSrcweir bClipped = sal_True; 1556cdf0e10cSrcweir } 1557cdf0e10cSrcweir 1558cdf0e10cSrcweir // Breite ausserhalb des Bereichs? 1559cdf0e10cSrcweir if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) ) 1560cdf0e10cSrcweir { 1561cdf0e10cSrcweir nWidth = mnOutOffX + mnOutWidth - nX; 1562cdf0e10cSrcweir bClipped = sal_True; 1563cdf0e10cSrcweir } 1564cdf0e10cSrcweir 1565cdf0e10cSrcweir // Hoehe ausserhalb des Bereichs? 1566cdf0e10cSrcweir if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) ) 1567cdf0e10cSrcweir { 1568cdf0e10cSrcweir nHeight = mnOutOffY + mnOutHeight - nY; 1569cdf0e10cSrcweir bClipped = sal_True; 1570cdf0e10cSrcweir } 1571cdf0e10cSrcweir 1572cdf0e10cSrcweir if ( bClipped ) 1573cdf0e10cSrcweir { 1574cdf0e10cSrcweir // Falls auf den sichtbaren Bereich geclipped wurde, 1575cdf0e10cSrcweir // muessen wir eine Bitmap in der rchtigen Groesse 1576cdf0e10cSrcweir // erzeugen, in die die geclippte Bitmap an die angepasste 1577cdf0e10cSrcweir // Position kopiert wird 1578cdf0e10cSrcweir VirtualDevice aVDev( *this ); 1579cdf0e10cSrcweir 1580cdf0e10cSrcweir if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) ) 1581cdf0e10cSrcweir { 1582cdf0e10cSrcweir if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() ) 1583cdf0e10cSrcweir { 15845f27b83cSArmin Le Grand SalTwoRect aPosAry; 1585cdf0e10cSrcweir 1586cdf0e10cSrcweir aPosAry.mnSrcX = nX; 1587cdf0e10cSrcweir aPosAry.mnSrcY = nY; 1588cdf0e10cSrcweir aPosAry.mnSrcWidth = nWidth; 1589cdf0e10cSrcweir aPosAry.mnSrcHeight = nHeight; 1590cdf0e10cSrcweir aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L; 1591cdf0e10cSrcweir aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L; 1592cdf0e10cSrcweir aPosAry.mnDestWidth = nWidth; 1593cdf0e10cSrcweir aPosAry.mnDestHeight = nHeight; 1594cdf0e10cSrcweir 1595cdf0e10cSrcweir if ( (nWidth > 0) && (nHeight > 0) ) 1596ff0f521cSArmin Le Grand { 15975f27b83cSArmin Le Grand (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( aPosAry, mpGraphics, this, this ); 1598ff0f521cSArmin Le Grand } 1599ff0f521cSArmin Le Grand else 1600ff0f521cSArmin Le Grand { 1601ff0f521cSArmin Le Grand OSL_ENSURE(false, "CopyBits with negative width or height (!)"); 1602ff0f521cSArmin Le Grand } 1603cdf0e10cSrcweir 1604cdf0e10cSrcweir aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() ); 1605cdf0e10cSrcweir } 1606cdf0e10cSrcweir else 1607cdf0e10cSrcweir bClipped = sal_False; 1608cdf0e10cSrcweir } 1609cdf0e10cSrcweir else 1610cdf0e10cSrcweir bClipped = sal_False; 1611cdf0e10cSrcweir } 1612cdf0e10cSrcweir 1613cdf0e10cSrcweir if ( !bClipped ) 1614cdf0e10cSrcweir { 1615cdf0e10cSrcweir SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this ); 1616cdf0e10cSrcweir 1617cdf0e10cSrcweir if( pSalBmp ) 1618cdf0e10cSrcweir { 1619cdf0e10cSrcweir ImpBitmap* pImpBmp = new ImpBitmap; 1620cdf0e10cSrcweir pImpBmp->ImplSetSalBitmap( pSalBmp ); 1621cdf0e10cSrcweir aBmp.ImplSetImpBitmap( pImpBmp ); 1622cdf0e10cSrcweir } 1623cdf0e10cSrcweir } 1624cdf0e10cSrcweir } 1625cdf0e10cSrcweir } 1626cdf0e10cSrcweir 1627cdf0e10cSrcweir return aBmp; 1628cdf0e10cSrcweir } 1629cdf0e10cSrcweir 1630cdf0e10cSrcweir // ------------------------------------------------------------------ 1631cdf0e10cSrcweir 1632cdf0e10cSrcweir BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const 1633cdf0e10cSrcweir { 1634cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1635cdf0e10cSrcweir 1636cdf0e10cSrcweir // #110958# Extract alpha value from VDev, if any 1637cdf0e10cSrcweir if( mpAlphaVDev ) 1638cdf0e10cSrcweir { 1639cdf0e10cSrcweir Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) ); 1640cdf0e10cSrcweir 1641cdf0e10cSrcweir // ensure 8 bit alpha 1642cdf0e10cSrcweir if( aAlphaBitmap.GetBitCount() > 8 ) 1643cdf0e10cSrcweir aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); 1644cdf0e10cSrcweir 1645cdf0e10cSrcweir return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) ); 1646cdf0e10cSrcweir } 1647cdf0e10cSrcweir else 1648cdf0e10cSrcweir return GetBitmap( rSrcPt, rSize ); 1649cdf0e10cSrcweir } 1650cdf0e10cSrcweir 1651cdf0e10cSrcweir // ------------------------------------------------------------------ 1652cdf0e10cSrcweir 1653cdf0e10cSrcweir void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize, 1654cdf0e10cSrcweir Bitmap& rBitmap ) const 1655cdf0e10cSrcweir { 1656cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1657cdf0e10cSrcweir 1658cdf0e10cSrcweir sal_Bool bOldMap = mbMap; 1659cdf0e10cSrcweir ((OutputDevice*)this)->mbMap = sal_False; 1660cdf0e10cSrcweir rBitmap = GetBitmap( rDestPt, rSize ); 1661cdf0e10cSrcweir ((OutputDevice*)this)->mbMap = bOldMap; 1662cdf0e10cSrcweir } 1663cdf0e10cSrcweir 1664cdf0e10cSrcweir // ------------------------------------------------------------------ 1665cdf0e10cSrcweir 1666cdf0e10cSrcweir Color OutputDevice::GetPixel( const Point& rPt ) const 1667cdf0e10cSrcweir { 1668cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1669cdf0e10cSrcweir 1670cdf0e10cSrcweir Color aColor; 1671cdf0e10cSrcweir 1672cdf0e10cSrcweir if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() ) 1673cdf0e10cSrcweir { 1674cdf0e10cSrcweir if ( mbInitClipRegion ) 1675cdf0e10cSrcweir ((OutputDevice*)this)->ImplInitClipRegion(); 1676cdf0e10cSrcweir 1677cdf0e10cSrcweir if ( !mbOutputClipped ) 1678cdf0e10cSrcweir { 1679cdf0e10cSrcweir const long nX = ImplLogicXToDevicePixel( rPt.X() ); 1680cdf0e10cSrcweir const long nY = ImplLogicYToDevicePixel( rPt.Y() ); 1681cdf0e10cSrcweir const SalColor aSalCol = mpGraphics->GetPixel( nX, nY, this ); 1682cdf0e10cSrcweir aColor.SetRed( SALCOLOR_RED( aSalCol ) ); 1683cdf0e10cSrcweir aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) ); 1684cdf0e10cSrcweir aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) ); 1685cdf0e10cSrcweir } 1686cdf0e10cSrcweir } 1687cdf0e10cSrcweir return aColor; 1688cdf0e10cSrcweir } 1689cdf0e10cSrcweir 1690cdf0e10cSrcweir // ------------------------------------------------------------------ 1691cdf0e10cSrcweir 1692cdf0e10cSrcweir Color* OutputDevice::GetPixel( const Polygon& rPts ) const 1693cdf0e10cSrcweir { 1694cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1695cdf0e10cSrcweir 1696cdf0e10cSrcweir Color* pColors = NULL; 1697cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize(); 1698cdf0e10cSrcweir 1699cdf0e10cSrcweir if( nSize ) 1700cdf0e10cSrcweir { 1701cdf0e10cSrcweir if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() ) 1702cdf0e10cSrcweir { 1703cdf0e10cSrcweir if ( mbInitClipRegion ) 1704cdf0e10cSrcweir ((OutputDevice*)this)->ImplInitClipRegion(); 1705cdf0e10cSrcweir 1706cdf0e10cSrcweir if ( !mbOutputClipped ) 1707cdf0e10cSrcweir { 1708cdf0e10cSrcweir pColors = new Color[ nSize ]; 1709cdf0e10cSrcweir 1710cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nSize; i++ ) 1711cdf0e10cSrcweir { 1712cdf0e10cSrcweir Color& rCol = pColors[ i ]; 1713cdf0e10cSrcweir const Point& rPt = rPts[ i ]; 1714cdf0e10cSrcweir const SalColor aSalCol( mpGraphics->GetPixel( ImplLogicXToDevicePixel( rPt.X() ), 1715cdf0e10cSrcweir ImplLogicYToDevicePixel( rPt.Y() ) , this) ); 1716cdf0e10cSrcweir 1717cdf0e10cSrcweir rCol.SetRed( SALCOLOR_RED( aSalCol ) ); 1718cdf0e10cSrcweir rCol.SetGreen( SALCOLOR_GREEN( aSalCol ) ); 1719cdf0e10cSrcweir rCol.SetBlue( SALCOLOR_BLUE( aSalCol ) ); 1720cdf0e10cSrcweir } 1721cdf0e10cSrcweir } 1722cdf0e10cSrcweir } 1723cdf0e10cSrcweir } 1724cdf0e10cSrcweir 1725cdf0e10cSrcweir return pColors; 1726cdf0e10cSrcweir } 1727cdf0e10cSrcweir 1728cdf0e10cSrcweir // ----------------------------------------------------------------------- 1729cdf0e10cSrcweir 1730cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt ) 1731cdf0e10cSrcweir { 1732cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" ); 1733cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1734cdf0e10cSrcweir 1735cdf0e10cSrcweir if ( mpMetaFile ) 1736cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPointAction( rPt ) ); 1737cdf0e10cSrcweir 1738cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() ) 1739cdf0e10cSrcweir return; 1740cdf0e10cSrcweir 1741cdf0e10cSrcweir Point aPt = ImplLogicToDevicePixel( rPt ); 1742cdf0e10cSrcweir 1743cdf0e10cSrcweir // we need a graphics 1744cdf0e10cSrcweir if ( !mpGraphics ) 1745cdf0e10cSrcweir { 1746cdf0e10cSrcweir if ( !ImplGetGraphics() ) 1747cdf0e10cSrcweir return; 1748cdf0e10cSrcweir } 1749cdf0e10cSrcweir 1750cdf0e10cSrcweir if ( mbInitClipRegion ) 1751cdf0e10cSrcweir ImplInitClipRegion(); 1752cdf0e10cSrcweir if ( mbOutputClipped ) 1753cdf0e10cSrcweir return; 1754cdf0e10cSrcweir 1755cdf0e10cSrcweir if ( mbInitLineColor ) 1756cdf0e10cSrcweir ImplInitLineColor(); 1757cdf0e10cSrcweir 1758cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), this ); 1759cdf0e10cSrcweir 1760cdf0e10cSrcweir if( mpAlphaVDev ) 1761cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPt ); 1762cdf0e10cSrcweir } 1763cdf0e10cSrcweir 1764cdf0e10cSrcweir // ----------------------------------------------------------------------- 1765cdf0e10cSrcweir 1766cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor ) 1767cdf0e10cSrcweir { 1768cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" ); 1769cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1770cdf0e10cSrcweir 1771cdf0e10cSrcweir Color aColor( rColor ); 1772cdf0e10cSrcweir 1773cdf0e10cSrcweir if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE | 1774cdf0e10cSrcweir DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE | 1775cdf0e10cSrcweir DRAWMODE_SETTINGSLINE ) ) 1776cdf0e10cSrcweir { 1777cdf0e10cSrcweir if( !ImplIsColorTransparent( aColor ) ) 1778cdf0e10cSrcweir { 1779cdf0e10cSrcweir if( mnDrawMode & DRAWMODE_BLACKLINE ) 1780cdf0e10cSrcweir { 1781cdf0e10cSrcweir aColor = Color( COL_BLACK ); 1782cdf0e10cSrcweir } 1783cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_WHITELINE ) 1784cdf0e10cSrcweir { 1785cdf0e10cSrcweir aColor = Color( COL_WHITE ); 1786cdf0e10cSrcweir } 1787cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_GRAYLINE ) 1788cdf0e10cSrcweir { 1789cdf0e10cSrcweir const sal_uInt8 cLum = aColor.GetLuminance(); 1790cdf0e10cSrcweir aColor = Color( cLum, cLum, cLum ); 1791cdf0e10cSrcweir } 1792cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_SETTINGSLINE ) 1793cdf0e10cSrcweir { 1794cdf0e10cSrcweir aColor = GetSettings().GetStyleSettings().GetFontColor(); 1795cdf0e10cSrcweir } 1796cdf0e10cSrcweir 1797cdf0e10cSrcweir if( mnDrawMode & DRAWMODE_GHOSTEDLINE ) 1798cdf0e10cSrcweir { 1799cdf0e10cSrcweir aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80, 1800cdf0e10cSrcweir ( aColor.GetGreen() >> 1 ) | 0x80, 1801cdf0e10cSrcweir ( aColor.GetBlue() >> 1 ) | 0x80 ); 1802cdf0e10cSrcweir } 1803cdf0e10cSrcweir } 1804cdf0e10cSrcweir } 1805cdf0e10cSrcweir 1806cdf0e10cSrcweir if ( mpMetaFile ) 1807cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) ); 1808cdf0e10cSrcweir 1809cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) || ImplIsRecordLayout() ) 1810cdf0e10cSrcweir return; 1811cdf0e10cSrcweir 1812cdf0e10cSrcweir Point aPt = ImplLogicToDevicePixel( rPt ); 1813cdf0e10cSrcweir 1814cdf0e10cSrcweir // we need a graphics 1815cdf0e10cSrcweir if ( !mpGraphics ) 1816cdf0e10cSrcweir { 1817cdf0e10cSrcweir if ( !ImplGetGraphics() ) 1818cdf0e10cSrcweir return; 1819cdf0e10cSrcweir } 1820cdf0e10cSrcweir 1821cdf0e10cSrcweir if ( mbInitClipRegion ) 1822cdf0e10cSrcweir ImplInitClipRegion(); 1823cdf0e10cSrcweir if ( mbOutputClipped ) 1824cdf0e10cSrcweir return; 1825cdf0e10cSrcweir 1826cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ), this ); 1827cdf0e10cSrcweir 1828cdf0e10cSrcweir if( mpAlphaVDev ) 1829cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPt ); 1830cdf0e10cSrcweir } 1831cdf0e10cSrcweir 1832cdf0e10cSrcweir // ----------------------------------------------------------------------- 1833cdf0e10cSrcweir 1834cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors ) 1835cdf0e10cSrcweir { 1836cdf0e10cSrcweir if ( !pColors ) 1837cdf0e10cSrcweir DrawPixel( rPts, GetLineColor() ); 1838cdf0e10cSrcweir else 1839cdf0e10cSrcweir { 1840cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" ); 1841cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); 1842cdf0e10cSrcweir DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" ); 1843cdf0e10cSrcweir 1844cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize(); 1845cdf0e10cSrcweir 1846cdf0e10cSrcweir if ( nSize ) 1847cdf0e10cSrcweir { 1848cdf0e10cSrcweir if ( mpMetaFile ) 1849cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSize; i++ ) 1850cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) ); 1851cdf0e10cSrcweir 1852cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) 1853cdf0e10cSrcweir return; 1854cdf0e10cSrcweir 1855cdf0e10cSrcweir // we need a graphics 1856cdf0e10cSrcweir if ( mpGraphics || ImplGetGraphics() ) 1857cdf0e10cSrcweir { 1858cdf0e10cSrcweir if ( mbInitClipRegion ) 1859cdf0e10cSrcweir ImplInitClipRegion(); 1860cdf0e10cSrcweir 1861cdf0e10cSrcweir if ( mbOutputClipped ) 1862cdf0e10cSrcweir return; 1863cdf0e10cSrcweir 1864cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSize; i++ ) 1865cdf0e10cSrcweir { 1866cdf0e10cSrcweir const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) ); 1867cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ), this ); 1868cdf0e10cSrcweir } 1869cdf0e10cSrcweir } 1870cdf0e10cSrcweir } 1871cdf0e10cSrcweir } 1872cdf0e10cSrcweir 1873cdf0e10cSrcweir if( mpAlphaVDev ) 1874cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPts, pColors ); 1875cdf0e10cSrcweir } 1876cdf0e10cSrcweir 1877cdf0e10cSrcweir // ----------------------------------------------------------------------- 1878cdf0e10cSrcweir 1879cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor ) 1880cdf0e10cSrcweir { 1881cdf0e10cSrcweir if( rColor != COL_TRANSPARENT && ! ImplIsRecordLayout() ) 1882cdf0e10cSrcweir { 1883cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize(); 1884cdf0e10cSrcweir Color* pColArray = new Color[ nSize ]; 1885cdf0e10cSrcweir 1886cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nSize; i++ ) 1887cdf0e10cSrcweir pColArray[ i ] = rColor; 1888cdf0e10cSrcweir 1889cdf0e10cSrcweir DrawPixel( rPts, pColArray ); 1890cdf0e10cSrcweir delete[] pColArray; 1891cdf0e10cSrcweir } 1892cdf0e10cSrcweir 1893cdf0e10cSrcweir if( mpAlphaVDev ) 1894cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPts, rColor ); 1895cdf0e10cSrcweir } 1896cdf0e10cSrcweir 1897cdf0e10cSrcweir // ------------------------------------------------------------------------ 1898cdf0e10cSrcweir 1899cdf0e10cSrcweir namespace 1900cdf0e10cSrcweir { 1901cdf0e10cSrcweir sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceOpaq, const sal_uInt8 nDestColor ) 1902cdf0e10cSrcweir { 1903cdf0e10cSrcweir int c = ( (int)nDestColor * ( 255 - nSourceOpaq ) ) 1904cdf0e10cSrcweir + (int)nSourceOpaq * (int)nSourceColor; 1905cdf0e10cSrcweir return sal_uInt8( c / 255 ); 1906cdf0e10cSrcweir } 1907cdf0e10cSrcweir } 1908cdf0e10cSrcweir 1909cdf0e10cSrcweir // ------------------------------------------------------------------------ 1910cdf0e10cSrcweir 1911cdf0e10cSrcweir Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp, 1912cdf0e10cSrcweir BitmapReadAccess* pP, 1913cdf0e10cSrcweir BitmapReadAccess* pA, 1914cdf0e10cSrcweir const Rectangle& aDstRect, 1915cdf0e10cSrcweir const sal_Int32 nOffY, 1916cdf0e10cSrcweir const sal_Int32 nDstHeight, 1917cdf0e10cSrcweir const sal_Int32 nOffX, 1918cdf0e10cSrcweir const sal_Int32 nDstWidth, 1919cdf0e10cSrcweir const long* pMapX, 1920cdf0e10cSrcweir const long* pMapY ) 1921cdf0e10cSrcweir { 1922cdf0e10cSrcweir BitmapColor aDstCol,aSrcCol; 1923cdf0e10cSrcweir Bitmap res; 1924cdf0e10cSrcweir int nX, nOutX, nY, nOutY; 1925cdf0e10cSrcweir 1926cdf0e10cSrcweir OSL_ENSURE(mpAlphaVDev, 1927cdf0e10cSrcweir "ImplBlendWithAlpha(): call me only with valid alpha VDev!" ); 1928cdf0e10cSrcweir 1929cdf0e10cSrcweir sal_Bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() ); 1930cdf0e10cSrcweir mpAlphaVDev->EnableMapMode(sal_False); 1931cdf0e10cSrcweir 1932cdf0e10cSrcweir Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) ); 1933cdf0e10cSrcweir BitmapWriteAccess* pAlphaW = aAlphaBitmap.AcquireWriteAccess(); 1934cdf0e10cSrcweir 1935cdf0e10cSrcweir if( GetBitCount() <= 8 ) 1936cdf0e10cSrcweir { 1937cdf0e10cSrcweir Bitmap aDither( aBmp.GetSizePixel(), 8 ); 1938cdf0e10cSrcweir BitmapColor aIndex( 0 ); 1939cdf0e10cSrcweir BitmapReadAccess* pB = aBmp.AcquireReadAccess(); 1940cdf0e10cSrcweir BitmapWriteAccess* pW = aDither.AcquireWriteAccess(); 1941cdf0e10cSrcweir 1942cdf0e10cSrcweir if( pB && pP && pA && pW && pAlphaW ) 1943cdf0e10cSrcweir { 1944cdf0e10cSrcweir for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) 1945cdf0e10cSrcweir { 1946cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1947cdf0e10cSrcweir const long nModY = ( nOutY & 0x0FL ) << 4L; 1948cdf0e10cSrcweir 1949cdf0e10cSrcweir for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) 1950cdf0e10cSrcweir { 1951cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1952cdf0e10cSrcweir const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ]; 1953cdf0e10cSrcweir 1954cdf0e10cSrcweir aSrcCol = pP->GetColor( nMapY, nMapX ); 1955cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX ); 195687bc88d3SHerbert Dürr const sal_uInt8 nSrcOpaq = 255 - pA->GetPixelIndex( nMapY, nMapX ); 195787bc88d3SHerbert Dürr const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixelIndex( nY, nX ); 1958cdf0e10cSrcweir 1959cdf0e10cSrcweir aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) ); 1960cdf0e10cSrcweir aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) ); 1961cdf0e10cSrcweir aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) ); 1962cdf0e10cSrcweir 1963cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] + 1964cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] + 1965cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) ); 1966cdf0e10cSrcweir pW->SetPixel( nY, nX, aIndex ); 1967cdf0e10cSrcweir 1968cdf0e10cSrcweir // Have to perform the compositing 'algebra' in 1969cdf0e10cSrcweir // the inverse alpha space (with 255 meaning 1970cdf0e10cSrcweir // opaque), otherwise, transitivity is not 1971cdf0e10cSrcweir // achieved. 1972cdf0e10cSrcweir const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq ); 1973cdf0e10cSrcweir 1974cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] + 1975cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] + 1976cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] ) ); 1977cdf0e10cSrcweir pAlphaW->SetPixel( nY, nX, aIndex ); 1978cdf0e10cSrcweir } 1979cdf0e10cSrcweir } 1980cdf0e10cSrcweir } 1981cdf0e10cSrcweir 1982cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 1983cdf0e10cSrcweir aDither.ReleaseAccess( pW ); 1984cdf0e10cSrcweir res = aDither; 1985cdf0e10cSrcweir } 1986cdf0e10cSrcweir else 1987cdf0e10cSrcweir { 1988cdf0e10cSrcweir BitmapWriteAccess* pB = aBmp.AcquireWriteAccess(); 1989cdf0e10cSrcweir if( pP && pA && pB ) 1990cdf0e10cSrcweir { 1991cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 1992cdf0e10cSrcweir { 1993cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 1994cdf0e10cSrcweir 1995cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 1996cdf0e10cSrcweir { 1997cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 1998cdf0e10cSrcweir 1999cdf0e10cSrcweir aSrcCol = pP->GetColor( nMapY, nMapX ); 2000cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX ); 200187bc88d3SHerbert Dürr const sal_uInt8 nSrcOpaq = 255 - pA->GetPixelIndex( nMapY, nMapX ); 200287bc88d3SHerbert Dürr const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixelIndex( nY, nX ); 2003cdf0e10cSrcweir 2004cdf0e10cSrcweir aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) ); 2005cdf0e10cSrcweir aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) ); 2006cdf0e10cSrcweir aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) ); 2007cdf0e10cSrcweir 2008cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol ); 2009cdf0e10cSrcweir 2010cdf0e10cSrcweir // Have to perform the compositing 'algebra' in 2011cdf0e10cSrcweir // the inverse alpha space (with 255 meaning 2012cdf0e10cSrcweir // opaque), otherwise, transitivity is not 2013cdf0e10cSrcweir // achieved. 2014cdf0e10cSrcweir const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq ); 2015cdf0e10cSrcweir 2016cdf0e10cSrcweir pAlphaW->SetPixel( nY, nX, Color(nSrcAlpha, nSrcAlpha, nSrcAlpha) ); 2017cdf0e10cSrcweir } 2018cdf0e10cSrcweir } 2019cdf0e10cSrcweir } 2020cdf0e10cSrcweir 2021cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 2022cdf0e10cSrcweir res = aBmp; 2023cdf0e10cSrcweir } 2024cdf0e10cSrcweir 2025cdf0e10cSrcweir aAlphaBitmap.ReleaseAccess( pAlphaW ); 2026cdf0e10cSrcweir mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap ); 2027cdf0e10cSrcweir mpAlphaVDev->EnableMapMode( bOldMapMode ); 2028cdf0e10cSrcweir 2029cdf0e10cSrcweir return res; 2030cdf0e10cSrcweir } 2031cdf0e10cSrcweir 2032cdf0e10cSrcweir // ------------------------------------------------------------------------ 2033cdf0e10cSrcweir 2034cdf0e10cSrcweir Bitmap OutputDevice::ImplBlend( Bitmap aBmp, 2035cdf0e10cSrcweir BitmapReadAccess* pP, 2036cdf0e10cSrcweir BitmapReadAccess* pA, 2037cdf0e10cSrcweir const sal_Int32 nOffY, 2038cdf0e10cSrcweir const sal_Int32 nDstHeight, 2039cdf0e10cSrcweir const sal_Int32 nOffX, 2040cdf0e10cSrcweir const sal_Int32 nDstWidth, 2041cdf0e10cSrcweir const Rectangle& aBmpRect, 2042cdf0e10cSrcweir const Size& aOutSz, 2043cdf0e10cSrcweir const bool bHMirr, 2044cdf0e10cSrcweir const bool bVMirr, 2045cdf0e10cSrcweir const long* pMapX, 2046cdf0e10cSrcweir const long* pMapY ) 2047cdf0e10cSrcweir { 2048cdf0e10cSrcweir BitmapColor aDstCol; 2049cdf0e10cSrcweir Bitmap res; 2050cdf0e10cSrcweir int nX, nOutX, nY, nOutY; 2051cdf0e10cSrcweir 2052cdf0e10cSrcweir if( GetBitCount() <= 8 ) 2053cdf0e10cSrcweir { 2054cdf0e10cSrcweir Bitmap aDither( aBmp.GetSizePixel(), 8 ); 2055cdf0e10cSrcweir BitmapColor aIndex( 0 ); 2056cdf0e10cSrcweir BitmapReadAccess* pB = aBmp.AcquireReadAccess(); 2057cdf0e10cSrcweir BitmapWriteAccess* pW = aDither.AcquireWriteAccess(); 2058cdf0e10cSrcweir 2059cdf0e10cSrcweir if( pB && pP && pA && pW ) 2060cdf0e10cSrcweir { 2061cdf0e10cSrcweir for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) 2062cdf0e10cSrcweir { 2063cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 2064cdf0e10cSrcweir const long nModY = ( nOutY & 0x0FL ) << 4L; 2065cdf0e10cSrcweir 2066cdf0e10cSrcweir for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) 2067cdf0e10cSrcweir { 2068cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 2069cdf0e10cSrcweir const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ]; 2070cdf0e10cSrcweir 2071cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX ); 207287bc88d3SHerbert Dürr aDstCol.Merge( pP->GetColor( nMapY, nMapX ), pA->GetPixelIndex( nMapY, nMapX ) ); 2073cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] + 2074cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] + 2075cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) ); 2076cdf0e10cSrcweir pW->SetPixel( nY, nX, aIndex ); 2077cdf0e10cSrcweir } 2078cdf0e10cSrcweir } 2079cdf0e10cSrcweir } 2080cdf0e10cSrcweir 2081cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 2082cdf0e10cSrcweir aDither.ReleaseAccess( pW ); 2083cdf0e10cSrcweir res = aDither; 2084cdf0e10cSrcweir } 2085cdf0e10cSrcweir else 2086cdf0e10cSrcweir { 2087cdf0e10cSrcweir BitmapWriteAccess* pB = aBmp.AcquireWriteAccess(); 2088cdf0e10cSrcweir 2089cdf0e10cSrcweir bool bFastBlend = false; 2090cdf0e10cSrcweir if( pP && pA && pB ) 2091cdf0e10cSrcweir { 2092cdf0e10cSrcweir SalTwoRect aTR; 2093cdf0e10cSrcweir aTR.mnSrcX = aBmpRect.Left(); 2094cdf0e10cSrcweir aTR.mnSrcY = aBmpRect.Top(); 2095cdf0e10cSrcweir aTR.mnSrcWidth = aBmpRect.GetWidth(); 2096cdf0e10cSrcweir aTR.mnSrcHeight = aBmpRect.GetHeight(); 2097cdf0e10cSrcweir aTR.mnDestX = nOffX; 2098cdf0e10cSrcweir aTR.mnDestY = nOffY; 2099cdf0e10cSrcweir aTR.mnDestWidth = aOutSz.Width(); 2100cdf0e10cSrcweir aTR.mnDestHeight= aOutSz.Height(); 2101cdf0e10cSrcweir 2102cdf0e10cSrcweir if( !bHMirr || !bVMirr ) 2103cdf0e10cSrcweir bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR ); 2104cdf0e10cSrcweir } 2105cdf0e10cSrcweir 2106cdf0e10cSrcweir if( pP && pA && pB && !bFastBlend ) 2107cdf0e10cSrcweir { 2108cdf0e10cSrcweir switch( pP->GetScanlineFormat() ) 2109cdf0e10cSrcweir { 2110cdf0e10cSrcweir case( BMP_FORMAT_8BIT_PAL ): 2111cdf0e10cSrcweir { 2112cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 2113cdf0e10cSrcweir { 2114cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 2115cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY ); 2116cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 2117cdf0e10cSrcweir 2118cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 2119cdf0e10cSrcweir { 2120cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 2121cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 2122cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ), 2123cdf0e10cSrcweir pAScan[ nMapX ] ) ); 2124cdf0e10cSrcweir } 2125cdf0e10cSrcweir } 2126cdf0e10cSrcweir } 2127cdf0e10cSrcweir break; 2128cdf0e10cSrcweir 2129cdf0e10cSrcweir case( BMP_FORMAT_24BIT_TC_BGR ): 2130cdf0e10cSrcweir { 2131cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 2132cdf0e10cSrcweir { 2133cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 2134cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY ); 2135cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 2136cdf0e10cSrcweir 2137cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 2138cdf0e10cSrcweir { 2139cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 2140cdf0e10cSrcweir Scanline pTmp = pPScan + nMapX * 3; 2141cdf0e10cSrcweir 2142cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 2143cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ], 2144cdf0e10cSrcweir pAScan[ nMapX ] ) ); 2145cdf0e10cSrcweir } 2146cdf0e10cSrcweir } 2147cdf0e10cSrcweir } 2148cdf0e10cSrcweir break; 2149cdf0e10cSrcweir 2150cdf0e10cSrcweir case( BMP_FORMAT_24BIT_TC_RGB ): 2151cdf0e10cSrcweir { 2152cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 2153cdf0e10cSrcweir { 2154cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 2155cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY ); 2156cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 2157cdf0e10cSrcweir 2158cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 2159cdf0e10cSrcweir { 2160cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 2161cdf0e10cSrcweir Scanline pTmp = pPScan + nMapX * 3; 2162cdf0e10cSrcweir 2163cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 2164cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ], 2165cdf0e10cSrcweir pAScan[ nMapX ] ) ); 2166cdf0e10cSrcweir } 2167cdf0e10cSrcweir } 2168cdf0e10cSrcweir } 2169cdf0e10cSrcweir break; 2170cdf0e10cSrcweir 2171cdf0e10cSrcweir default: 2172cdf0e10cSrcweir { 2173cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ ) 2174cdf0e10cSrcweir { 2175cdf0e10cSrcweir const long nMapY = pMapY[ nY ]; 2176cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY ); 2177cdf0e10cSrcweir 2178cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ ) 2179cdf0e10cSrcweir { 2180cdf0e10cSrcweir const long nMapX = pMapX[ nX ]; 2181cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX ); 2182cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ), 2183cdf0e10cSrcweir pAScan[ nMapX ] ) ); 2184cdf0e10cSrcweir } 2185cdf0e10cSrcweir } 2186cdf0e10cSrcweir } 2187cdf0e10cSrcweir break; 2188cdf0e10cSrcweir } 2189cdf0e10cSrcweir } 2190cdf0e10cSrcweir 2191cdf0e10cSrcweir aBmp.ReleaseAccess( pB ); 2192cdf0e10cSrcweir res = aBmp; 2193cdf0e10cSrcweir } 2194cdf0e10cSrcweir 2195cdf0e10cSrcweir return res; 2196cdf0e10cSrcweir } 2197cdf0e10cSrcweir 2198cdf0e10cSrcweir // ------------------------------------------------------------------------ 2199cdf0e10cSrcweir 2200cdf0e10cSrcweir void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha, 2201cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize, 2202cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel ) 2203cdf0e10cSrcweir { 2204cdf0e10cSrcweir const Point aNullPt; 2205cdf0e10cSrcweir Point aOutPt( LogicToPixel( rDestPt ) ); 2206cdf0e10cSrcweir Size aOutSz( LogicToPixel( rDestSize ) ); 2207cdf0e10cSrcweir Rectangle aDstRect( aNullPt, GetOutputSizePixel() ); 2208cdf0e10cSrcweir const sal_Bool bHMirr = aOutSz.Width() < 0, bVMirr = aOutSz.Height() < 0; 2209cdf0e10cSrcweir 2210cdf0e10cSrcweir if( OUTDEV_WINDOW == meOutDevType ) 2211cdf0e10cSrcweir { 2212cdf0e10cSrcweir const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() ); 2213cdf0e10cSrcweir 2214cdf0e10cSrcweir if( !aPaintRgn.IsNull() ) 2215cdf0e10cSrcweir aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) ); 2216cdf0e10cSrcweir } 2217cdf0e10cSrcweir 2218cdf0e10cSrcweir if( bHMirr ) 2219cdf0e10cSrcweir { 2220cdf0e10cSrcweir aOutSz.Width() = -aOutSz.Width(); 2221cdf0e10cSrcweir aOutPt.X() -= ( aOutSz.Width() - 1L ); 2222cdf0e10cSrcweir } 2223cdf0e10cSrcweir 2224cdf0e10cSrcweir if( bVMirr ) 2225cdf0e10cSrcweir { 2226cdf0e10cSrcweir aOutSz.Height() = -aOutSz.Height(); 2227cdf0e10cSrcweir aOutPt.Y() -= ( aOutSz.Height() - 1L ); 2228cdf0e10cSrcweir } 2229cdf0e10cSrcweir 2230cdf0e10cSrcweir if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() ) 2231cdf0e10cSrcweir { 2232cdf0e10cSrcweir bool bNativeAlpha = false; 2233cdf0e10cSrcweir static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA"); 2234cdf0e10cSrcweir // #i83087# Naturally, system alpha blending cannot work with 2235cdf0e10cSrcweir // separate alpha VDev 22365f27b83cSArmin Le Grand bool bTryDirectPaint(!mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr); 22375f27b83cSArmin Le Grand 22385f27b83cSArmin Le Grand #ifdef WNT 22395f27b83cSArmin Le Grand if(bTryDirectPaint) 22405f27b83cSArmin Le Grand { 22415f27b83cSArmin Le Grand // only paint direct when no scaling and no MapMode, else the 22425f27b83cSArmin Le Grand // more expensive conversions may be done for short-time Bitmap/BitmapEx 22435f27b83cSArmin Le Grand // used for buffering only 22445f27b83cSArmin Le Grand if(!IsMapMode() && rSrcSizePixel.Width() == aOutSz.Width() && rSrcSizePixel.Height() == aOutSz.Height()) 22455f27b83cSArmin Le Grand { 22465f27b83cSArmin Le Grand bTryDirectPaint = false; 22475f27b83cSArmin Le Grand } 22485f27b83cSArmin Le Grand } 22495f27b83cSArmin Le Grand #endif 22505f27b83cSArmin Le Grand 22515f27b83cSArmin Le Grand if(bTryDirectPaint) 2252cdf0e10cSrcweir { 2253cdf0e10cSrcweir Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY ); 2254cdf0e10cSrcweir SalTwoRect aTR = { 2255cdf0e10cSrcweir rSrcPtPixel.X(), rSrcPtPixel.Y(), 2256cdf0e10cSrcweir rSrcSizePixel.Width(), rSrcSizePixel.Height(), 2257cdf0e10cSrcweir aRelPt.X(), aRelPt.Y(), 2258cdf0e10cSrcweir aOutSz.Width(), aOutSz.Height() 2259cdf0e10cSrcweir }; 2260cdf0e10cSrcweir SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap(); 2261cdf0e10cSrcweir SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap(); 2262cdf0e10cSrcweir bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this ); 2263cdf0e10cSrcweir } 2264cdf0e10cSrcweir 2265cdf0e10cSrcweir VirtualDevice* pOldVDev = mpAlphaVDev; 2266cdf0e10cSrcweir 2267cdf0e10cSrcweir Rectangle aBmpRect( aNullPt, rBmp.GetSizePixel() ); 2268cdf0e10cSrcweir if( !bNativeAlpha 2269cdf0e10cSrcweir && !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() ) 2270cdf0e10cSrcweir { 2271cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; mpMetaFile = NULL; 2272cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; mbMap = sal_False; 2273cdf0e10cSrcweir Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) ); 2274cdf0e10cSrcweir 2275cdf0e10cSrcweir // #109044# The generated bitmap need not necessarily be 2276cdf0e10cSrcweir // of aDstRect dimensions, it's internally clipped to 2277cdf0e10cSrcweir // window bounds. Thus, we correct the dest size here, 2278cdf0e10cSrcweir // since we later use it (in nDstWidth/Height) for pixel 2279cdf0e10cSrcweir // access) 2280cdf0e10cSrcweir // #i38887# reading from screen may sometimes fail 2281cdf0e10cSrcweir if( aBmp.ImplGetImpBitmap() ) 2282cdf0e10cSrcweir aDstRect.SetSize( aBmp.GetSizePixel() ); 2283cdf0e10cSrcweir 2284cdf0e10cSrcweir BitmapColor aDstCol; 2285cdf0e10cSrcweir const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight(); 2286cdf0e10cSrcweir const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight(); 2287cdf0e10cSrcweir const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height(); 2288cdf0e10cSrcweir // calculate offset in original bitmap 2289cdf0e10cSrcweir // in RTL case this is a little more complicated since the contents of the 2290cdf0e10cSrcweir // bitmap is not mirrored (it never is), however the paint region and bmp region 2291cdf0e10cSrcweir // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these 2292cdf0e10cSrcweir // is content wise somewhere else and needs to take mirroring into account 2293cdf0e10cSrcweir const long nOffX = IsRTLEnabled() 2294cdf0e10cSrcweir ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X()) 2295cdf0e10cSrcweir : aDstRect.Left() - aOutPt.X(), 2296cdf0e10cSrcweir nOffY = aDstRect.Top() - aOutPt.Y(); 2297cdf0e10cSrcweir long nX, nOutX, nY, nOutY; 2298cdf0e10cSrcweir long nMirrOffX = 0; 2299cdf0e10cSrcweir long nMirrOffY = 0; 2300cdf0e10cSrcweir long* pMapX = new long[ nDstWidth ]; 2301cdf0e10cSrcweir long* pMapY = new long[ nDstHeight ]; 2302cdf0e10cSrcweir 2303cdf0e10cSrcweir // create horizontal mapping table 2304cdf0e10cSrcweir if( bHMirr ) 2305cdf0e10cSrcweir nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1; 2306cdf0e10cSrcweir 2307cdf0e10cSrcweir for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ ) 2308cdf0e10cSrcweir { 2309cdf0e10cSrcweir pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth; 2310cdf0e10cSrcweir if( bHMirr ) 2311cdf0e10cSrcweir pMapX[ nX ] = nMirrOffX - pMapX[ nX ]; 2312cdf0e10cSrcweir } 2313cdf0e10cSrcweir 2314cdf0e10cSrcweir // create vertical mapping table 2315cdf0e10cSrcweir if( bVMirr ) 2316cdf0e10cSrcweir nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1; 2317cdf0e10cSrcweir 2318cdf0e10cSrcweir for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ ) 2319cdf0e10cSrcweir { 2320cdf0e10cSrcweir pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight; 2321cdf0e10cSrcweir 2322cdf0e10cSrcweir if( bVMirr ) 2323cdf0e10cSrcweir pMapY[ nY ] = nMirrOffY - pMapY[ nY ]; 2324cdf0e10cSrcweir } 2325cdf0e10cSrcweir 2326cdf0e10cSrcweir BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess(); 2327cdf0e10cSrcweir BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess(); 2328cdf0e10cSrcweir 2329cdf0e10cSrcweir DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || 2330cdf0e10cSrcweir pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK, 2331cdf0e10cSrcweir "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" ); 2332cdf0e10cSrcweir 2333cdf0e10cSrcweir // #i38887# reading from screen may sometimes fail 2334cdf0e10cSrcweir if( aBmp.ImplGetImpBitmap() ) 2335cdf0e10cSrcweir { 2336cdf0e10cSrcweir Bitmap aTmp; 2337cdf0e10cSrcweir 2338cdf0e10cSrcweir if( mpAlphaVDev ) 2339cdf0e10cSrcweir { 2340cdf0e10cSrcweir aTmp = ImplBlendWithAlpha( 2341cdf0e10cSrcweir aBmp,pP,pA, 2342cdf0e10cSrcweir aDstRect, 2343cdf0e10cSrcweir nOffY,nDstHeight, 2344cdf0e10cSrcweir nOffX,nDstWidth, 2345cdf0e10cSrcweir pMapX,pMapY ); 2346cdf0e10cSrcweir } 2347cdf0e10cSrcweir else 2348cdf0e10cSrcweir { 2349cdf0e10cSrcweir aTmp = ImplBlend( 2350cdf0e10cSrcweir aBmp,pP,pA, 2351cdf0e10cSrcweir nOffY,nDstHeight, 2352cdf0e10cSrcweir nOffX,nDstWidth, 2353cdf0e10cSrcweir aBmpRect,aOutSz, 2354cdf0e10cSrcweir bHMirr,bVMirr, 2355cdf0e10cSrcweir pMapX,pMapY ); 2356cdf0e10cSrcweir } 2357cdf0e10cSrcweir 2358cdf0e10cSrcweir // #110958# Disable alpha VDev, we're doing the necessary 23596d53c851Smseidel // stuff explicitly further below 2360cdf0e10cSrcweir if( mpAlphaVDev ) 2361cdf0e10cSrcweir mpAlphaVDev = NULL; 2362cdf0e10cSrcweir 2363cdf0e10cSrcweir DrawBitmap( aDstRect.TopLeft(), 2364cdf0e10cSrcweir aTmp ); 2365cdf0e10cSrcweir 2366cdf0e10cSrcweir // #110958# Enable alpha VDev again 2367cdf0e10cSrcweir mpAlphaVDev = pOldVDev; 2368cdf0e10cSrcweir } 2369cdf0e10cSrcweir 2370cdf0e10cSrcweir ( (Bitmap&) rBmp ).ReleaseAccess( pP ); 2371cdf0e10cSrcweir ( (AlphaMask&) rAlpha ).ReleaseAccess( pA ); 2372cdf0e10cSrcweir 2373cdf0e10cSrcweir delete[] pMapX; 2374cdf0e10cSrcweir delete[] pMapY; 2375cdf0e10cSrcweir mbMap = bOldMap; 2376cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 2377cdf0e10cSrcweir } 2378cdf0e10cSrcweir } 2379cdf0e10cSrcweir } 2380cdf0e10cSrcweir 2381cdf0e10cSrcweir // ------------------------------------------------------------------------ 2382cdf0e10cSrcweir 2383cdf0e10cSrcweir void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask, 2384cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize, 2385cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel ) 2386cdf0e10cSrcweir { 2387cdf0e10cSrcweir Point aPt; 2388cdf0e10cSrcweir Point aDestPt( LogicToPixel( rDestPt ) ); 2389cdf0e10cSrcweir Size aDestSz( LogicToPixel( rDestSize ) ); 2390cdf0e10cSrcweir Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel ); 2391cdf0e10cSrcweir 2392cdf0e10cSrcweir aSrcRect.Justify(); 2393cdf0e10cSrcweir 2394cdf0e10cSrcweir if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() ) 2395cdf0e10cSrcweir { 2396cdf0e10cSrcweir Bitmap aPaint( rBmp ), aMask( rMask ); 2397cdf0e10cSrcweir sal_uLong nMirrFlags = 0UL; 2398cdf0e10cSrcweir 2399cdf0e10cSrcweir if( aMask.GetBitCount() > 1 ) 2400cdf0e10cSrcweir aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); 2401cdf0e10cSrcweir 2402cdf0e10cSrcweir // mirrored horizontically 2403cdf0e10cSrcweir if( aDestSz.Width() < 0L ) 2404cdf0e10cSrcweir { 2405cdf0e10cSrcweir aDestSz.Width() = -aDestSz.Width(); 2406cdf0e10cSrcweir aDestPt.X() -= ( aDestSz.Width() - 1L ); 2407cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ; 2408cdf0e10cSrcweir } 2409cdf0e10cSrcweir 2410cdf0e10cSrcweir // mirrored vertically 2411cdf0e10cSrcweir if( aDestSz.Height() < 0L ) 2412cdf0e10cSrcweir { 2413cdf0e10cSrcweir aDestSz.Height() = -aDestSz.Height(); 2414cdf0e10cSrcweir aDestPt.Y() -= ( aDestSz.Height() - 1L ); 2415cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT; 2416cdf0e10cSrcweir } 2417cdf0e10cSrcweir 2418cdf0e10cSrcweir // source cropped? 2419cdf0e10cSrcweir if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) ) 2420cdf0e10cSrcweir { 2421cdf0e10cSrcweir aPaint.Crop( aSrcRect ); 2422cdf0e10cSrcweir aMask.Crop( aSrcRect ); 2423cdf0e10cSrcweir } 2424cdf0e10cSrcweir 2425cdf0e10cSrcweir // destination mirrored 2426cdf0e10cSrcweir if( nMirrFlags ) 2427cdf0e10cSrcweir { 2428cdf0e10cSrcweir aPaint.Mirror( nMirrFlags ); 2429cdf0e10cSrcweir aMask.Mirror( nMirrFlags ); 2430cdf0e10cSrcweir } 2431cdf0e10cSrcweir 2432cdf0e10cSrcweir // we always want to have a mask 2433cdf0e10cSrcweir if( aMask.IsEmpty() ) 2434cdf0e10cSrcweir { 2435cdf0e10cSrcweir aMask = Bitmap( aSrcRect.GetSize(), 1 ); 2436cdf0e10cSrcweir aMask.Erase( Color( COL_BLACK ) ); 2437cdf0e10cSrcweir } 2438cdf0e10cSrcweir 2439cdf0e10cSrcweir // do painting 2440cdf0e10cSrcweir const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight(); 2441e6f63103SArmin Le Grand long nX, nY; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight; 2442cdf0e10cSrcweir long* pMapX = new long[ nSrcWidth + 1 ]; 2443cdf0e10cSrcweir long* pMapY = new long[ nSrcHeight + 1 ]; 2444cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 2445cdf0e10cSrcweir 2446cdf0e10cSrcweir mbMap = sal_False; 2447cdf0e10cSrcweir 2448cdf0e10cSrcweir // create forward mapping tables 2449cdf0e10cSrcweir for( nX = 0L; nX <= nSrcWidth; nX++ ) 2450cdf0e10cSrcweir pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth ); 2451cdf0e10cSrcweir 2452cdf0e10cSrcweir for( nY = 0L; nY <= nSrcHeight; nY++ ) 2453cdf0e10cSrcweir pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight ); 2454cdf0e10cSrcweir 2455cdf0e10cSrcweir // walk through all rectangles of mask 2456e6f63103SArmin Le Grand const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel()))); 2457e6f63103SArmin Le Grand RectangleVector aRectangles; 2458e6f63103SArmin Le Grand aWorkRgn.GetRegionRectangles(aRectangles); 2459cdf0e10cSrcweir 2460e6f63103SArmin Le Grand for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) 2461cdf0e10cSrcweir { 2462e6f63103SArmin Le Grand const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]); 2463e6f63103SArmin Le Grand const Size aMapSz( 2464e6f63103SArmin Le Grand pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1 2465e6f63103SArmin Le Grand pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y 2466cdf0e10cSrcweir Bitmap aBandBmp(aPaint); 2467cdf0e10cSrcweir 2468e6f63103SArmin Le Grand aBandBmp.Crop(*aRectIter); 2469cdf0e10cSrcweir ImplDrawBitmap(aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION); 2470cdf0e10cSrcweir } 2471cdf0e10cSrcweir 2472e6f63103SArmin Le Grand //Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) ); 2473e6f63103SArmin Le Grand //ImplRegionInfo aInfo; 2474e6f63103SArmin Le Grand //sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2475e6f63103SArmin Le Grand // 2476e6f63103SArmin Le Grand //while( bRgnRect ) 2477e6f63103SArmin Le Grand //{ 2478e6f63103SArmin Le Grand // Bitmap aBandBmp( aPaint ); 2479e6f63103SArmin Le Grand // const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) ); 2480e6f63103SArmin Le Grand // const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] ); 2481e6f63103SArmin Le Grand // const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() ); 2482e6f63103SArmin Le Grand // 2483e6f63103SArmin Le Grand // aBandBmp.Crop( aBandRect ); 2484e6f63103SArmin Le Grand // ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION ); 2485e6f63103SArmin Le Grand // bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2486e6f63103SArmin Le Grand //} 2487e6f63103SArmin Le Grand 2488cdf0e10cSrcweir mbMap = bOldMap; 2489cdf0e10cSrcweir 2490cdf0e10cSrcweir delete[] pMapX; 2491cdf0e10cSrcweir delete[] pMapY; 2492cdf0e10cSrcweir } 2493cdf0e10cSrcweir } 2494cdf0e10cSrcweir 2495cdf0e10cSrcweir // ------------------------------------------------------------------------ 2496cdf0e10cSrcweir 2497cdf0e10cSrcweir void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor, 2498cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize, 2499cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel ) 2500cdf0e10cSrcweir { 2501cdf0e10cSrcweir Point aPt; 2502cdf0e10cSrcweir Point aDestPt( LogicToPixel( rDestPt ) ); 2503cdf0e10cSrcweir Size aDestSz( LogicToPixel( rDestSize ) ); 2504cdf0e10cSrcweir Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel ); 2505cdf0e10cSrcweir 2506cdf0e10cSrcweir aSrcRect.Justify(); 2507cdf0e10cSrcweir 2508cdf0e10cSrcweir if( !rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() ) 2509cdf0e10cSrcweir { 2510cdf0e10cSrcweir Bitmap aMask( rMask ); 2511cdf0e10cSrcweir sal_uLong nMirrFlags = 0UL; 2512cdf0e10cSrcweir 2513cdf0e10cSrcweir if( aMask.GetBitCount() > 1 ) 2514cdf0e10cSrcweir aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); 2515cdf0e10cSrcweir 2516cdf0e10cSrcweir // mirrored horizontically 2517cdf0e10cSrcweir if( aDestSz.Width() < 0L ) 2518cdf0e10cSrcweir { 2519cdf0e10cSrcweir aDestSz.Width() = -aDestSz.Width(); 2520cdf0e10cSrcweir aDestPt.X() -= ( aDestSz.Width() - 1L ); 2521cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ; 2522cdf0e10cSrcweir } 2523cdf0e10cSrcweir 2524cdf0e10cSrcweir // mirrored vertically 2525cdf0e10cSrcweir if( aDestSz.Height() < 0L ) 2526cdf0e10cSrcweir { 2527cdf0e10cSrcweir aDestSz.Height() = -aDestSz.Height(); 2528cdf0e10cSrcweir aDestPt.Y() -= ( aDestSz.Height() - 1L ); 2529cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT; 2530cdf0e10cSrcweir } 2531cdf0e10cSrcweir 2532cdf0e10cSrcweir // source cropped? 2533cdf0e10cSrcweir if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) ) 2534cdf0e10cSrcweir aMask.Crop( aSrcRect ); 2535cdf0e10cSrcweir 2536cdf0e10cSrcweir // destination mirrored 2537cdf0e10cSrcweir if( nMirrFlags ) 2538cdf0e10cSrcweir aMask.Mirror( nMirrFlags ); 2539cdf0e10cSrcweir 2540cdf0e10cSrcweir // do painting 2541cdf0e10cSrcweir const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight(); 2542e6f63103SArmin Le Grand long nX, nY; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight; 2543cdf0e10cSrcweir long* pMapX = new long[ nSrcWidth + 1 ]; 2544cdf0e10cSrcweir long* pMapY = new long[ nSrcHeight + 1 ]; 2545cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; 2546cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; 2547cdf0e10cSrcweir 2548cdf0e10cSrcweir mpMetaFile = NULL; 2549cdf0e10cSrcweir mbMap = sal_False; 2550cdf0e10cSrcweir Push( PUSH_FILLCOLOR | PUSH_LINECOLOR ); 2551cdf0e10cSrcweir SetLineColor( rMaskColor ); 2552cdf0e10cSrcweir SetFillColor( rMaskColor ); 2553cdf0e10cSrcweir ImplInitLineColor(); 2554cdf0e10cSrcweir ImplInitFillColor(); 2555cdf0e10cSrcweir 2556cdf0e10cSrcweir // create forward mapping tables 2557cdf0e10cSrcweir for( nX = 0L; nX <= nSrcWidth; nX++ ) 2558cdf0e10cSrcweir pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth ); 2559cdf0e10cSrcweir 2560cdf0e10cSrcweir for( nY = 0L; nY <= nSrcHeight; nY++ ) 2561cdf0e10cSrcweir pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight ); 2562cdf0e10cSrcweir 2563cdf0e10cSrcweir // walk through all rectangles of mask 2564e6f63103SArmin Le Grand const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel()))); 2565e6f63103SArmin Le Grand RectangleVector aRectangles; 2566e6f63103SArmin Le Grand aWorkRgn.GetRegionRectangles(aRectangles); 2567cdf0e10cSrcweir 2568e6f63103SArmin Le Grand for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) 2569cdf0e10cSrcweir { 2570e6f63103SArmin Le Grand const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]); 2571e6f63103SArmin Le Grand const Size aMapSz( 2572e6f63103SArmin Le Grand pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1 2573e6f63103SArmin Le Grand pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y 2574cdf0e10cSrcweir 2575cdf0e10cSrcweir DrawRect(Rectangle(aMapPt, aMapSz)); 2576cdf0e10cSrcweir } 2577cdf0e10cSrcweir 2578e6f63103SArmin Le Grand //Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) ); 2579e6f63103SArmin Le Grand //ImplRegionInfo aInfo; 2580e6f63103SArmin Le Grand //sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2581e6f63103SArmin Le Grand // 2582e6f63103SArmin Le Grand //while( bRgnRect ) 2583e6f63103SArmin Le Grand //{ 2584e6f63103SArmin Le Grand // const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] ); 2585e6f63103SArmin Le Grand // const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() ); 2586e6f63103SArmin Le Grand // 2587e6f63103SArmin Le Grand // DrawRect( Rectangle( aMapPt, aMapSz ) ); 2588e6f63103SArmin Le Grand // bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight ); 2589e6f63103SArmin Le Grand //} 2590e6f63103SArmin Le Grand 2591cdf0e10cSrcweir Pop(); 2592cdf0e10cSrcweir delete[] pMapX; 2593cdf0e10cSrcweir delete[] pMapY; 2594cdf0e10cSrcweir mbMap = bOldMap; 2595cdf0e10cSrcweir mpMetaFile = pOldMetaFile; 2596cdf0e10cSrcweir } 2597cdf0e10cSrcweir } 2598