LCOV - code coverage report
Current view: top level - vcl/source/outdev - bitmap.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 448 651 68.8 %
Date: 2014-11-03 Functions: 23 24 95.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <vcl/bitmap.hxx>
      21             : #include <vcl/bitmapex.hxx>
      22             : #include <vcl/bmpacc.hxx>
      23             : #include <vcl/outdev.hxx>
      24             : #include <vcl/virdev.hxx>
      25             : #include <vcl/image.hxx>
      26             : 
      27             : #include <bmpfast.hxx>
      28             : #include <salgdi.hxx>
      29             : #include <impbmp.hxx>
      30             : #include <image.h>
      31             : 
      32             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      33             : #include <boost/scoped_array.hpp>
      34             : 
      35             : 
      36      234701 : void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
      37             : {
      38      234701 :     const Size aSizePix( rBitmap.GetSizePixel() );
      39      234701 :     DrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
      40      234701 : }
      41             : 
      42        1676 : void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
      43             : {
      44        1676 :     DrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
      45        1676 : }
      46             : 
      47             : 
      48      236377 : void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
      49             :                                    const Point& rSrcPtPixel, const Size& rSrcSizePixel,
      50             :                                    const Bitmap& rBitmap, const sal_uLong nAction )
      51             : {
      52      236377 :     if( ImplIsRecordLayout() )
      53         943 :         return;
      54             : 
      55      236377 :     if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
      56             :     {
      57           0 :         return;
      58             :     }
      59      236377 :     if ( ROP_INVERT == meRasterOp )
      60             :     {
      61           0 :         DrawRect( Rectangle( rDestPt, rDestSize ) );
      62           0 :         return;
      63             :     }
      64             : 
      65      236377 :     Bitmap aBmp( rBitmap );
      66             : 
      67      236377 :     if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
      68             :                              DRAWMODE_GRAYBITMAP  | DRAWMODE_GHOSTEDBITMAP ) )
      69             :     {
      70           0 :         if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
      71             :         {
      72             :             sal_uInt8 cCmpVal;
      73             : 
      74           0 :             if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
      75           0 :                 cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
      76             :             else
      77           0 :                 cCmpVal = 255;
      78             : 
      79           0 :             Color aCol( cCmpVal, cCmpVal, cCmpVal );
      80           0 :             Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
      81           0 :             SetLineColor( aCol );
      82           0 :             SetFillColor( aCol );
      83           0 :             DrawRect( Rectangle( rDestPt, rDestSize ) );
      84           0 :             Pop();
      85           0 :             return;
      86             :         }
      87           0 :         else if( !!aBmp )
      88             :         {
      89           0 :             if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
      90           0 :                 aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
      91             : 
      92           0 :             if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
      93           0 :                 aBmp.Convert( BMP_CONVERSION_GHOSTED );
      94             :         }
      95             :     }
      96             : 
      97      236377 :     if ( mpMetaFile )
      98             :     {
      99         886 :         switch( nAction )
     100             :         {
     101             :             case( META_BMP_ACTION ):
     102           0 :                 mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
     103           0 :             break;
     104             : 
     105             :             case( META_BMPSCALE_ACTION ):
     106         886 :                 mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
     107         886 :             break;
     108             : 
     109             :             case( META_BMPSCALEPART_ACTION ):
     110             :                 mpMetaFile->AddAction( new MetaBmpScalePartAction(
     111           0 :                     rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
     112           0 :             break;
     113             :         }
     114             :     }
     115             : 
     116      236377 :     if ( !IsDeviceOutputNecessary() )
     117         943 :         return;
     118             : 
     119      235434 :     if ( !mpGraphics )
     120           0 :         if ( !AcquireGraphics() )
     121           0 :             return;
     122             : 
     123      235434 :     if ( mbInitClipRegion )
     124       11740 :         InitClipRegion();
     125             : 
     126      235434 :     if ( mbOutputClipped )
     127           0 :         return;
     128             : 
     129      235434 :     if( !aBmp.IsEmpty() )
     130             :     {
     131             :         SalTwoRect aPosAry;
     132             : 
     133      235396 :         aPosAry.mnSrcX = rSrcPtPixel.X();
     134      235396 :         aPosAry.mnSrcY = rSrcPtPixel.Y();
     135      235396 :         aPosAry.mnSrcWidth = rSrcSizePixel.Width();
     136      235396 :         aPosAry.mnSrcHeight = rSrcSizePixel.Height();
     137      235396 :         aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
     138      235396 :         aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
     139      235396 :         aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
     140      235396 :         aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
     141             : 
     142      235396 :         if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
     143             :         {
     144      235396 :             const sal_uLong nMirrFlags = AdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
     145             : 
     146      235396 :             if ( nMirrFlags )
     147           0 :                 aBmp.Mirror( nMirrFlags );
     148             : 
     149      235396 :             if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
     150             :             {
     151      235396 :                 if ( nAction == META_BMPSCALE_ACTION )
     152         790 :                     ScaleBitmap (aBmp, aPosAry);
     153             : 
     154      235396 :                 mpGraphics->DrawBitmap( aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this );
     155             :             }
     156             :         }
     157             :     }
     158             : 
     159      235434 :     if( mpAlphaVDev )
     160             :     {
     161             :         // #i32109#: Make bitmap area opaque
     162           0 :         mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
     163      235434 :     }
     164             : }
     165             : 
     166           0 : Bitmap OutputDevice::GetDownsampledBitmap( const Size& rDstSz,
     167             :                                            const Point& rSrcPt, const Size& rSrcSz,
     168             :                                            const Bitmap& rBmp, long nMaxBmpDPIX, long nMaxBmpDPIY )
     169             : {
     170           0 :     Bitmap aBmp( rBmp );
     171             : 
     172           0 :     if( !aBmp.IsEmpty() )
     173             :     {
     174           0 :         Point           aPoint;
     175           0 :         const Rectangle aBmpRect( aPoint, aBmp.GetSizePixel() );
     176           0 :         Rectangle       aSrcRect( rSrcPt, rSrcSz );
     177             : 
     178             :         // do cropping if necessary
     179           0 :         if( aSrcRect.Intersection( aBmpRect ) != aBmpRect )
     180             :         {
     181           0 :             if( !aSrcRect.IsEmpty() )
     182           0 :                 aBmp.Crop( aSrcRect );
     183             :             else
     184           0 :                 aBmp.SetEmpty();
     185             :         }
     186             : 
     187           0 :         if( !aBmp.IsEmpty() )
     188             :         {
     189             :             // do downsampling if necessary
     190           0 :             Size aDstSizeTwip( PixelToLogic( LogicToPixel( rDstSz ), MAP_TWIP ) );
     191             : 
     192             :             // #103209# Normalize size (mirroring has to happen outside of this method)
     193           0 :             aDstSizeTwip = Size( labs(aDstSizeTwip.Width()), labs(aDstSizeTwip.Height()) );
     194             : 
     195           0 :             const Size      aBmpSize( aBmp.GetSizePixel() );
     196           0 :             const double    fBmpPixelX = aBmpSize.Width();
     197           0 :             const double    fBmpPixelY = aBmpSize.Height();
     198           0 :             const double    fMaxPixelX = aDstSizeTwip.Width() * nMaxBmpDPIX / 1440.0;
     199           0 :             const double    fMaxPixelY = aDstSizeTwip.Height() * nMaxBmpDPIY / 1440.0;
     200             : 
     201             :             // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
     202           0 :             if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
     203           0 :                   ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
     204           0 :                 ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
     205             :             {
     206             :                 // do scaling
     207           0 :                 Size            aNewBmpSize;
     208           0 :                 const double    fBmpWH = fBmpPixelX / fBmpPixelY;
     209           0 :                 const double    fMaxWH = fMaxPixelX / fMaxPixelY;
     210             : 
     211           0 :                 if( fBmpWH < fMaxWH )
     212             :                 {
     213           0 :                     aNewBmpSize.Width() = FRound( fMaxPixelY * fBmpWH );
     214           0 :                     aNewBmpSize.Height() = FRound( fMaxPixelY );
     215             :                 }
     216           0 :                 else if( fBmpWH > 0.0 )
     217             :                 {
     218           0 :                     aNewBmpSize.Width() = FRound( fMaxPixelX );
     219           0 :                     aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
     220             :                 }
     221             : 
     222           0 :                 if( aNewBmpSize.Width() && aNewBmpSize.Height() )
     223           0 :                     aBmp.Scale( aNewBmpSize );
     224             :                 else
     225           0 :                     aBmp.SetEmpty();
     226             :             }
     227             :         }
     228             :     }
     229             : 
     230           0 :     return aBmp;
     231             : }
     232             : 
     233       72206 : void OutputDevice::DrawBitmapEx( const Point& rDestPt,
     234             :                                  const BitmapEx& rBitmapEx )
     235             : {
     236       72206 :     if( ImplIsRecordLayout() )
     237       72206 :         return;
     238             : 
     239       72206 :     if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
     240             :     {
     241       10036 :         DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
     242             :     }
     243             :     else
     244             :     {
     245       62170 :         const Size aSizePix( rBitmapEx.GetSizePixel() );
     246       62170 :         DrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
     247             :     }
     248             : }
     249             : 
     250       16116 : void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
     251             :                                  const BitmapEx& rBitmapEx )
     252             : {
     253       16116 :     if( ImplIsRecordLayout() )
     254       16116 :         return;
     255             : 
     256       16116 :     if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
     257             :     {
     258         948 :         DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
     259             :     }
     260             :     else
     261             :     {
     262       15168 :         DrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
     263             :     }
     264             : }
     265             : 
     266             : 
     267      308066 : void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
     268             :                                  const Point& rSrcPtPixel, const Size& rSrcSizePixel,
     269             :                                  const BitmapEx& rBitmapEx, const sal_uLong nAction )
     270             : {
     271             : 
     272      308066 :     if( ImplIsRecordLayout() )
     273           0 :         return;
     274             : 
     275      308066 :     if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
     276             :     {
     277           0 :         DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
     278             :     }
     279             :     else
     280             :     {
     281      308066 :         if ( mnDrawMode & DRAWMODE_NOBITMAP )
     282         684 :             return;
     283             : 
     284      308066 :         if ( ROP_INVERT == meRasterOp )
     285             :         {
     286           0 :             DrawRect( Rectangle( rDestPt, rDestSize ) );
     287           0 :             return;
     288             :         }
     289             : 
     290      308066 :         BitmapEx aBmpEx( rBitmapEx );
     291             : 
     292      308066 :         if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
     293             :                                  DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
     294             :         {
     295           0 :             if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
     296             :             {
     297           0 :                 Bitmap  aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
     298             :                 sal_uInt8   cCmpVal;
     299             : 
     300           0 :                 if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
     301           0 :                     cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
     302             :                 else
     303           0 :                     cCmpVal = 255;
     304             : 
     305           0 :                 aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
     306             : 
     307           0 :                 if( aBmpEx.IsAlpha() )
     308             :                 {
     309             :                     // Create one-bit mask out of alpha channel, by
     310             :                     // thresholding it at alpha=0.5. As
     311             :                     // DRAWMODE_BLACK/WHITEBITMAP requires monochrome
     312             :                     // output, having alpha-induced grey levels is not
     313             :                     // acceptable.
     314           0 :                     Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() );
     315           0 :                     aMask.MakeMono( 129 );
     316           0 :                     aBmpEx = BitmapEx( aColorBmp, aMask );
     317             :                 }
     318             :                 else
     319             :                 {
     320           0 :                     aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
     321           0 :                 }
     322             :             }
     323           0 :             else if( !!aBmpEx )
     324             :             {
     325           0 :                 if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
     326           0 :                     aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
     327             : 
     328           0 :                 if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
     329           0 :                     aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
     330             :             }
     331             :         }
     332             : 
     333      308066 :         if ( mpMetaFile )
     334             :         {
     335         467 :             switch( nAction )
     336             :             {
     337             :                 case( META_BMPEX_ACTION ):
     338           6 :                     mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
     339           6 :                 break;
     340             : 
     341             :                 case( META_BMPEXSCALE_ACTION ):
     342          78 :                     mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
     343          78 :                 break;
     344             : 
     345             :                 case( META_BMPEXSCALEPART_ACTION ):
     346             :                     mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
     347         383 :                                                                          rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
     348         383 :                 break;
     349             :             }
     350             :         }
     351             : 
     352      308066 :         if ( !IsDeviceOutputNecessary() )
     353         141 :             return;
     354             : 
     355      307925 :         if ( !mpGraphics )
     356          78 :             if ( !AcquireGraphics() )
     357           0 :                 return;
     358             : 
     359      307925 :         if ( mbInitClipRegion )
     360      156908 :             InitClipRegion();
     361             : 
     362      307925 :         if ( mbOutputClipped )
     363         543 :             return;
     364             : 
     365      307382 :         DrawDeviceBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmpEx );
     366             :     }
     367             : }
     368             : 
     369      251133 : Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
     370             : {
     371      251133 :     Bitmap  aBmp;
     372      251133 :     long    nX = ImplLogicXToDevicePixel( rSrcPt.X() );
     373      251133 :     long    nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
     374      251133 :     long    nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
     375      251133 :     long    nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
     376             : 
     377      251133 :     if ( mpGraphics || AcquireGraphics() )
     378             :     {
     379      251133 :         if ( nWidth > 0 && nHeight  > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY))
     380             :         {
     381      250977 :             Rectangle   aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
     382      250977 :             bool        bClipped = false;
     383             : 
     384             :             // X-Coordinate outside of draw area?
     385      250977 :             if ( nX < mnOutOffX )
     386             :             {
     387           0 :                 nWidth -= ( mnOutOffX - nX );
     388           0 :                 nX = mnOutOffX;
     389           0 :                 bClipped = true;
     390             :             }
     391             : 
     392             :             // Y-Coordinate outside of draw area?
     393      250977 :             if ( nY < mnOutOffY )
     394             :             {
     395           0 :                 nHeight -= ( mnOutOffY - nY );
     396           0 :                 nY = mnOutOffY;
     397           0 :                 bClipped = true;
     398             :             }
     399             : 
     400             :             // Width outside of draw area?
     401      250977 :             if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
     402             :             {
     403           0 :                 nWidth  = mnOutOffX + mnOutWidth - nX;
     404           0 :                 bClipped = true;
     405             :             }
     406             : 
     407             :             // Height outside of draw area?
     408      250977 :             if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
     409             :             {
     410           0 :                 nHeight = mnOutOffY + mnOutHeight - nY;
     411           0 :                 bClipped = true;
     412             :             }
     413             : 
     414      250977 :             if ( bClipped )
     415             :             {
     416             :                 // If the visible part has been clipped, we have to create a
     417             :                 // Bitmap with the correct size in which we copy the clipped
     418             :                 // Bitmap to the correct position.
     419           0 :                 VirtualDevice aVDev( *this );
     420             : 
     421           0 :                 if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
     422             :                 {
     423           0 :                     if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->AcquireGraphics() )
     424             :                     {
     425             :                         SalTwoRect aPosAry;
     426             : 
     427           0 :                         aPosAry.mnSrcX = nX;
     428           0 :                         aPosAry.mnSrcY = nY;
     429           0 :                         aPosAry.mnSrcWidth = nWidth;
     430           0 :                         aPosAry.mnSrcHeight = nHeight;
     431           0 :                         aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
     432           0 :                         aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
     433           0 :                         aPosAry.mnDestWidth = nWidth;
     434           0 :                         aPosAry.mnDestHeight = nHeight;
     435             : 
     436           0 :                         if ( (nWidth > 0) && (nHeight > 0) )
     437             :                         {
     438           0 :                             (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( aPosAry, mpGraphics, this, this );
     439             :                         }
     440             :                         else
     441             :                         {
     442             :                             OSL_ENSURE(false, "CopyBits with negative width or height (!)");
     443             :                         }
     444             : 
     445           0 :                         aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
     446             :                      }
     447             :                      else
     448           0 :                         bClipped = false;
     449             :                 }
     450             :                 else
     451           0 :                     bClipped = false;
     452             :             }
     453             : 
     454      250977 :             if ( !bClipped )
     455             :             {
     456      250977 :                 SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
     457             : 
     458      250977 :                 if( pSalBmp )
     459             :                 {
     460      250977 :                     ImpBitmap* pImpBmp = new ImpBitmap;
     461      250977 :                     pImpBmp->ImplSetSalBitmap( pSalBmp );
     462      250977 :                     aBmp.ImplSetImpBitmap( pImpBmp );
     463             :                 }
     464             :             }
     465             :         }
     466             :     }
     467             : 
     468      251133 :     return aBmp;
     469             : }
     470             : 
     471        6631 : BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
     472             : {
     473             : 
     474             :     // #110958# Extract alpha value from VDev, if any
     475        6631 :     if( mpAlphaVDev )
     476             :     {
     477        6631 :         Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
     478             : 
     479             :         // ensure 8 bit alpha
     480        6631 :         if( aAlphaBitmap.GetBitCount() > 8 )
     481        6593 :             aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
     482             : 
     483        6631 :         return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
     484             :     }
     485             :     else
     486           0 :         return GetBitmap( rSrcPt, rSize );
     487             : }
     488             : 
     489      307382 : void OutputDevice::DrawDeviceBitmap( const Point& rDestPt, const Size& rDestSize,
     490             :                                      const Point& rSrcPtPixel, const Size& rSrcSizePixel,
     491             :                                      BitmapEx& rBitmapEx )
     492             : {
     493      307382 :     if (rBitmapEx.IsAlpha())
     494             :     {
     495      288015 :         DrawDeviceAlphaBitmap(rBitmapEx.GetBitmap(), rBitmapEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel);
     496             :     }
     497       19367 :     else if (!!rBitmapEx)
     498             :     {
     499             :         SalTwoRect aPosAry;
     500             : 
     501       19367 :         aPosAry.mnSrcX = rSrcPtPixel.X();
     502       19367 :         aPosAry.mnSrcY = rSrcPtPixel.Y();
     503       19367 :         aPosAry.mnSrcWidth = rSrcSizePixel.Width();
     504       19367 :         aPosAry.mnSrcHeight = rSrcSizePixel.Height();
     505       19367 :         aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
     506       19367 :         aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
     507       19367 :         aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
     508       19367 :         aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
     509             : 
     510       19367 :         const sal_uLong nMirrFlags = AdjustTwoRect(aPosAry, rBitmapEx.GetSizePixel());
     511             : 
     512       19367 :         if (aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight)
     513             :         {
     514             : 
     515       19367 :             if (nMirrFlags)
     516           0 :                 rBitmapEx.Mirror(nMirrFlags);
     517             : 
     518       19367 :             const SalBitmap* pSalSrcBmp = rBitmapEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap();
     519       19367 :             const ImpBitmap* pMaskBmp = rBitmapEx.ImplGetMaskImpBitmap();
     520             : 
     521       19367 :             if (pMaskBmp)
     522             :             {
     523       19367 :                 SalBitmap* pSalAlphaBmp = pMaskBmp->ImplGetSalBitmap();
     524       19367 :                 bool bTryDirectPaint(pSalSrcBmp && pSalAlphaBmp);
     525             : 
     526       19367 :                 if (bTryDirectPaint)
     527             :                 {
     528             :                     // only paint direct when no scaling and no MapMode, else the
     529             :                     // more expensive conversions may be done for short-time Bitmap/BitmapEx
     530             :                     // used for buffering only
     531       19367 :                     if(!IsMapMode() && aPosAry.mnSrcWidth == aPosAry.mnDestWidth && aPosAry.mnSrcHeight == aPosAry.mnDestHeight)
     532             :                     {
     533       19277 :                         bTryDirectPaint = false;
     534             :                     }
     535             :                 }
     536             : 
     537       19367 :                 if (bTryDirectPaint && mpGraphics->DrawAlphaBitmap(aPosAry, *pSalSrcBmp, *pSalAlphaBmp, this))
     538             :                 {
     539             :                     // tried to paint as alpha directly. If tis worked, we are done (except
     540             :                     // alpha, see below)
     541             :                 }
     542             :                 else
     543             :                 {
     544             :                     // #4919452# reduce operation area to bounds of
     545             :                     // cliprect. since masked transparency involves
     546             :                     // creation of a large vdev and copying the screen
     547             :                     // content into that (slooow read from framebuffer),
     548             :                     // that should considerably increase performance for
     549             :                     // large bitmaps and small clippings.
     550             : 
     551             :                     // Note that this optimization is a workaround for a
     552             :                     // Writer peculiarity, namely, to decompose background
     553             :                     // graphics into myriads of disjunct, tiny
     554             :                     // rectangles. That otherwise kills us here, since for
     555             :                     // transparent output, SAL always prepares the whole
     556             :                     // bitmap, if aPosAry contains the whole bitmap (and
     557             :                     // it's _not_ to blame for that).
     558             : 
     559             :                     // Note the call to ImplPixelToDevicePixel(), since
     560             :                     // aPosAry already contains the mnOutOff-offsets, they
     561             :                     // also have to be applied to the region
     562       19367 :                     Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
     563             : 
     564             :                     // TODO: Also respect scaling (that's a bit tricky,
     565             :                     // since the source points have to move fractional
     566             :                     // amounts (which is not possible, thus has to be
     567             :                     // emulated by increases copy area)
     568             :                     // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
     569             :                     // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
     570             : 
     571             :                     // for now, only identity scales allowed
     572       39897 :                     if (!aClipRegionBounds.IsEmpty() &&
     573       20518 :                         aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
     574        1151 :                         aPosAry.mnDestHeight == aPosAry.mnSrcHeight)
     575             :                     {
     576             :                         // now intersect dest rect with clip region
     577             :                         aClipRegionBounds.Intersection(Rectangle(aPosAry.mnDestX,
     578             :                                                                  aPosAry.mnDestY,
     579        1151 :                                                                  aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
     580        2302 :                                                                  aPosAry.mnDestY + aPosAry.mnDestHeight - 1));
     581             : 
     582             :                         // Note: I could theoretically optimize away the
     583             :                         // DrawBitmap below, if the region is empty
     584             :                         // here. Unfortunately, cannot rule out that
     585             :                         // somebody relies on the side effects.
     586        1151 :                         if (!aClipRegionBounds.IsEmpty())
     587             :                         {
     588        1151 :                             aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
     589        1151 :                             aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
     590        1151 :                             aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
     591        1151 :                             aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
     592             : 
     593        1151 :                             aPosAry.mnDestX = aClipRegionBounds.Left();
     594        1151 :                             aPosAry.mnDestY = aClipRegionBounds.Top();
     595        1151 :                             aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
     596        1151 :                             aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
     597             :                         }
     598             :                     }
     599             : 
     600             :                     mpGraphics->DrawBitmap(aPosAry, *pSalSrcBmp,
     601       19367 :                                            *pMaskBmp->ImplGetSalBitmap(),
     602       19367 :                                            this);
     603             :                 }
     604             : 
     605             :                 // #110958# Paint mask to alpha channel. Luckily, the
     606             :                 // black and white representation of the mask maps to
     607             :                 // the alpha channel
     608             : 
     609             :                 // #i25167# Restrict mask painting to _opaque_ areas
     610             :                 // of the mask, otherwise we spoil areas where no
     611             :                 // bitmap content was ever visible. Interestingly
     612             :                 // enough, this can be achieved by taking the mask as
     613             :                 // the transparency mask of itself
     614       19367 :                 if (mpAlphaVDev)
     615             :                     mpAlphaVDev->DrawBitmapEx(rDestPt,
     616             :                                               rDestSize,
     617             :                                               BitmapEx(rBitmapEx.GetMask(),
     618         308 :                                                        rBitmapEx.GetMask()));
     619             :             }
     620             :             else
     621             :             {
     622           0 :                 mpGraphics->DrawBitmap(aPosAry, *pSalSrcBmp, this);
     623             : 
     624           0 :                 if (mpAlphaVDev)
     625             :                 {
     626             :                     // #i32109#: Make bitmap area opaque
     627           0 :                     mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
     628             :                 }
     629             :             }
     630             :         }
     631             :     }
     632      307382 : }
     633             : 
     634      288015 : void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& rAlpha,
     635             :                                     const Point& rDestPt, const Size& rDestSize,
     636             :                                     const Point& rSrcPtPixel, const Size& rSrcSizePixel )
     637             : {
     638      288015 :     Point       aOutPt( LogicToPixel( rDestPt ) );
     639      288015 :     Size        aOutSz( LogicToPixel( rDestSize ) );
     640      288015 :     Rectangle   aDstRect( Point(), GetOutputSizePixel() );
     641      288015 :     const bool  bHMirr = aOutSz.Width() < 0;
     642      288015 :     const bool  bVMirr = aOutSz.Height() < 0;
     643             : 
     644      288015 :     ClipToPaintRegion(aDstRect);
     645             : 
     646      288015 :     if( bHMirr )
     647             :     {
     648           0 :         aOutSz.Width() = -aOutSz.Width();
     649           0 :         aOutPt.X() -= ( aOutSz.Width() - 1L );
     650             :     }
     651             : 
     652      288015 :     if( bVMirr )
     653             :     {
     654           0 :         aOutSz.Height() = -aOutSz.Height();
     655           0 :         aOutPt.Y() -= ( aOutSz.Height() - 1L );
     656             :     }
     657             : 
     658      288015 :     if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
     659             :     {
     660      211707 :         bool bNativeAlpha = false;
     661      211707 :         static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
     662             :         // #i83087# Naturally, system alpha blending cannot work with
     663             :         // separate alpha VDev
     664      211707 :         bool bTryDirectPaint(!mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr);
     665             : 
     666             : #ifdef WNT
     667             :         if(bTryDirectPaint)
     668             :         {
     669             :             // only paint direct when no scaling and no MapMode, else the
     670             :             // more expensive conversions may be done for short-time Bitmap/BitmapEx
     671             :             // used for buffering only
     672             :             if(!IsMapMode() && rSrcSizePixel.Width() == aOutSz.Width() && rSrcSizePixel.Height() == aOutSz.Height())
     673             :             {
     674             :                 bTryDirectPaint = false;
     675             :             }
     676             :         }
     677             : #endif
     678             : 
     679      211707 :         if(bTryDirectPaint)
     680             :         {
     681      211632 :             Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY );
     682             :             SalTwoRect aTR = {
     683      423264 :                 rSrcPtPixel.X(), rSrcPtPixel.Y(),
     684      423264 :                 rSrcSizePixel.Width(), rSrcSizePixel.Height(),
     685      423264 :                 aRelPt.X(), aRelPt.Y(),
     686      423264 :                 aOutSz.Width(), aOutSz.Height()
     687     1693056 :             };
     688      211632 :             SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap();
     689      211632 :             SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap();
     690      211632 :             bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this );
     691             :         }
     692             : 
     693      211707 :         VirtualDevice* pOldVDev = mpAlphaVDev;
     694             : 
     695      211707 :         Rectangle aBmpRect( Point(), rBmp.GetSizePixel() );
     696      635121 :         if( !bNativeAlpha
     697      846828 :                 &&  !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
     698             :         {
     699             :             // The scaling in this code path produces really ugly results - it
     700             :             // does the most trivial scaling with no smoothing.
     701             : 
     702      211707 :             GDIMetaFile*    pOldMetaFile = mpMetaFile;
     703      211707 :             const bool      bOldMap = mbMap;
     704      211707 :             mpMetaFile = NULL; // fdo#55044 reset before GetBitmap!
     705      211707 :             mbMap = false;
     706      211707 :             Bitmap          aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
     707             : 
     708             :             // #109044# The generated bitmap need not necessarily be
     709             :             // of aDstRect dimensions, it's internally clipped to
     710             :             // window bounds. Thus, we correct the dest size here,
     711             :             // since we later use it (in nDstWidth/Height) for pixel
     712             :             // access)
     713             :             // #i38887# reading from screen may sometimes fail
     714      211707 :             if( aBmp.ImplGetImpBitmap() )
     715      211707 :                 aDstRect.SetSize( aBmp.GetSizePixel() );
     716             : 
     717      423414 :             BitmapColor     aDstCol;
     718      211707 :             const long      nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
     719      211707 :             const long      nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
     720      211707 :             const long      nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
     721             :             // calculate offset in original bitmap
     722             :             // in RTL case this is a little more complicated since the contents of the
     723             :             // bitmap is not mirrored (it never is), however the paint region and bmp region
     724             :             // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
     725             :             // is content wise somewhere else and needs to take mirroring into account
     726      211707 :             const long      nOffX = IsRTLEnabled()
     727          39 :                                     ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X())
     728      211746 :                                     : aDstRect.Left() - aOutPt.X(),
     729      211707 :                             nOffY = aDstRect.Top() - aOutPt.Y();
     730             :             long            nX, nOutX, nY, nOutY;
     731      211707 :             long            nMirrOffX = 0;
     732      211707 :             long            nMirrOffY = 0;
     733      423414 :             boost::scoped_array<long> pMapX(new long[ nDstWidth ]);
     734      423414 :             boost::scoped_array<long> pMapY(new long[ nDstHeight ]);
     735             : 
     736             :             // create horizontal mapping table
     737      211707 :             if( bHMirr )
     738           0 :                 nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
     739             : 
     740     8297159 :             for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
     741             :             {
     742     8085452 :                 pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
     743     8085452 :                 if( bHMirr )
     744           0 :                     pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
     745             :             }
     746             : 
     747             :             // create vertical mapping table
     748      211707 :             if( bVMirr )
     749           0 :                 nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
     750             : 
     751     7917610 :             for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
     752             :             {
     753     7705903 :                 pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
     754             : 
     755     7705903 :                 if( bVMirr )
     756           0 :                     pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
     757             :             }
     758             : 
     759      211707 :             BitmapReadAccess*   pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
     760      211707 :             BitmapReadAccess*   pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
     761             : 
     762             :             DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
     763             :                         pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
     764             :                         "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
     765             : 
     766             :             // #i38887# reading from screen may sometimes fail
     767      211707 :             if( aBmp.ImplGetImpBitmap() )
     768             :             {
     769      211707 :                 Bitmap aTmp;
     770             : 
     771      211707 :                 if( mpAlphaVDev )
     772             :                 {
     773         150 :                     aTmp = BlendBitmapWithAlpha(
     774             :                         aBmp,pP,pA,
     775             :                         aDstRect,
     776             :                         nOffY,nDstHeight,
     777             :                         nOffX,nDstWidth,
     778         150 :                         pMapX.get(),pMapY.get() );
     779             :                 }
     780             :                 else
     781             :                 {
     782      423264 :                     aTmp = BlendBitmap(
     783             :                         aBmp,pP,pA,
     784             :                         nOffY,nDstHeight,
     785             :                         nOffX,nDstWidth,
     786             :                         aBmpRect,aOutSz,
     787             :                         bHMirr,bVMirr,
     788      423264 :                         pMapX.get(),pMapY.get() );
     789             :                 }
     790             : 
     791             :                 // #110958# Disable alpha VDev, we're doing the necessary
     792             :                 // stuff explicitly furher below
     793      211707 :                 if( mpAlphaVDev )
     794          75 :                     mpAlphaVDev = NULL;
     795             : 
     796             :                 DrawBitmap( aDstRect.TopLeft(),
     797      211707 :                             aTmp );
     798             : 
     799             :                 // #110958# Enable alpha VDev again
     800      211707 :                 mpAlphaVDev = pOldVDev;
     801             :             }
     802             : 
     803      211707 :             ( (Bitmap&) rBmp ).ReleaseAccess( pP );
     804      211707 :             ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
     805             : 
     806      211707 :             mbMap = bOldMap;
     807      423414 :             mpMetaFile = pOldMetaFile;
     808             :         }
     809             :     }
     810      288015 : }
     811             : 
     812         790 : void OutputDevice::ScaleBitmap (Bitmap &rBmp, SalTwoRect &rPosAry)
     813             : {
     814         790 :     const double nScaleX = rPosAry.mnDestWidth  / static_cast<double>( rPosAry.mnSrcWidth );
     815         790 :     const double nScaleY = rPosAry.mnDestHeight / static_cast<double>( rPosAry.mnSrcHeight );
     816             : 
     817             :     // If subsampling, use Bitmap::Scale for subsampling for better quality.
     818         790 :     if ( nScaleX < 1.0 || nScaleY < 1.0 )
     819             :     {
     820          94 :         rBmp.Scale ( nScaleX, nScaleY );
     821          94 :         rPosAry.mnSrcWidth = rPosAry.mnDestWidth;
     822          94 :         rPosAry.mnSrcHeight = rPosAry.mnDestHeight;
     823             :     }
     824         790 : }
     825             : 
     826          34 : bool OutputDevice::DrawTransformBitmapExDirect(
     827             :         const basegfx::B2DHomMatrix& aFullTransform,
     828             :         const BitmapEx& rBitmapEx)
     829             : {
     830          34 :     bool bDone = false;
     831             : 
     832             :     // try to paint directly
     833          34 :     const basegfx::B2DPoint aNull(aFullTransform * basegfx::B2DPoint(0.0, 0.0));
     834          68 :     const basegfx::B2DPoint aTopX(aFullTransform * basegfx::B2DPoint(1.0, 0.0));
     835          68 :     const basegfx::B2DPoint aTopY(aFullTransform * basegfx::B2DPoint(0.0, 1.0));
     836          34 :     SalBitmap* pSalSrcBmp = rBitmapEx.GetBitmap().ImplGetImpBitmap()->ImplGetSalBitmap();
     837          34 :     SalBitmap* pSalAlphaBmp = 0;
     838             : 
     839          34 :     if(rBitmapEx.IsTransparent())
     840             :     {
     841          34 :         if(rBitmapEx.IsAlpha())
     842             :         {
     843          34 :             pSalAlphaBmp = rBitmapEx.GetAlpha().ImplGetImpBitmap()->ImplGetSalBitmap();
     844             :         }
     845             :         else
     846             :         {
     847           0 :             pSalAlphaBmp = rBitmapEx.GetMask().ImplGetImpBitmap()->ImplGetSalBitmap();
     848             :         }
     849             :     }
     850             : 
     851             :     bDone = mpGraphics->DrawTransformedBitmap(
     852             :         aNull,
     853             :         aTopX,
     854             :         aTopY,
     855             :         *pSalSrcBmp,
     856             :         pSalAlphaBmp,
     857          34 :         this);
     858             : 
     859          68 :     return bDone;
     860             : };
     861             : 
     862          34 : bool OutputDevice::TransformAndReduceBitmapExToTargetRange(
     863             :         const basegfx::B2DHomMatrix& aFullTransform,
     864             :         basegfx::B2DRange &aVisibleRange,
     865             :         double &fMaximumArea)
     866             : {
     867             :     // limit TargetRange to existing pixels (if pixel device)
     868             :     // first get discrete range of object
     869          34 :     basegfx::B2DRange aFullPixelRange(aVisibleRange);
     870             : 
     871          34 :     aFullPixelRange.transform(aFullTransform);
     872             : 
     873          34 :     if(basegfx::fTools::equalZero(aFullPixelRange.getWidth()) || basegfx::fTools::equalZero(aFullPixelRange.getHeight()))
     874             :     {
     875             :         // object is outside of visible area
     876           0 :         return false;
     877             :     }
     878             : 
     879             :     // now get discrete target pixels; start with OutDev pixel size and evtl.
     880             :     // intersect with active clipping area
     881             :     basegfx::B2DRange aOutPixel(
     882             :         0.0,
     883             :         0.0,
     884          68 :         GetOutputSizePixel().Width(),
     885         102 :         GetOutputSizePixel().Height());
     886             : 
     887          34 :     if(IsClipRegion())
     888             :     {
     889           0 :         const Rectangle aRegionRectangle(GetActiveClipRegion().GetBoundRect());
     890             : 
     891             :         aOutPixel.intersect( // caution! Range from rectangle, one too much (!)
     892             :             basegfx::B2DRange(
     893           0 :                 aRegionRectangle.Left(),
     894           0 :                 aRegionRectangle.Top(),
     895           0 :                 aRegionRectangle.Right() + 1,
     896           0 :                 aRegionRectangle.Bottom() + 1));
     897             :     }
     898             : 
     899          34 :     if(aOutPixel.isEmpty())
     900             :     {
     901             :         // no active output area
     902           0 :         return false;
     903             :     }
     904             : 
     905             :     // if aFullPixelRange is not completely inside of aOutPixel,
     906             :     // reduction of target pixels is possible
     907          34 :     basegfx::B2DRange aVisiblePixelRange(aFullPixelRange);
     908             : 
     909          34 :     if(!aOutPixel.isInside(aFullPixelRange))
     910             :     {
     911           6 :         aVisiblePixelRange.intersect(aOutPixel);
     912             : 
     913           6 :         if(aVisiblePixelRange.isEmpty())
     914             :         {
     915             :             // nothing in visible part, reduces to nothing
     916           0 :             return false;
     917             :         }
     918             : 
     919             :         // aVisiblePixelRange contains the reduced output area in
     920             :         // discrete coordinates. To make it useful everywhere, make it relative to
     921             :         // the object range
     922           6 :         basegfx::B2DHomMatrix aMakeVisibleRangeRelative;
     923             : 
     924           6 :         aVisibleRange = aVisiblePixelRange;
     925             :         aMakeVisibleRangeRelative.translate(
     926           6 :             -aFullPixelRange.getMinX(),
     927          12 :             -aFullPixelRange.getMinY());
     928             :         aMakeVisibleRangeRelative.scale(
     929           6 :             1.0 / aFullPixelRange.getWidth(),
     930          12 :             1.0 / aFullPixelRange.getHeight());
     931           6 :         aVisibleRange.transform(aMakeVisibleRangeRelative);
     932             :     }
     933             : 
     934             :     // for pixel devices, do *not* limit size, else OutputDevice::DrawDeviceAlphaBitmap
     935             :     // will create another, badly scaled bitmap to do the job. Nonetheless, do a
     936             :     // maximum clipping of something big (1600x1280x2). Add 1.0 to avoid rounding
     937             :     // errors in rough estimations
     938          34 :     const double fNewMaxArea(aVisiblePixelRange.getWidth() * aVisiblePixelRange.getHeight());
     939             : 
     940          34 :     fMaximumArea = std::min(4096000.0, fNewMaxArea + 1.0);
     941             : 
     942          34 :     return true;
     943             : }
     944             : 
     945        4214 : void OutputDevice::DrawTransformedBitmapEx(
     946             :     const basegfx::B2DHomMatrix& rTransformation,
     947             :     const BitmapEx& rBitmapEx)
     948             : {
     949        4214 :     if( ImplIsRecordLayout() )
     950        4180 :         return;
     951             : 
     952        4214 :     if(rBitmapEx.IsEmpty())
     953           0 :         return;
     954             : 
     955        4214 :     if ( mnDrawMode & DRAWMODE_NOBITMAP )
     956           0 :         return;
     957             : 
     958             :     // decompose matrix to check rotation and shear
     959        4248 :     basegfx::B2DVector aScale, aTranslate;
     960             :     double fRotate, fShearX;
     961        4214 :     rTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
     962        4214 :     const bool bRotated(!basegfx::fTools::equalZero(fRotate));
     963        4214 :     const bool bSheared(!basegfx::fTools::equalZero(fShearX));
     964        4214 :     const bool bMirroredX(basegfx::fTools::less(aScale.getX(), 0.0));
     965        4214 :     const bool bMirroredY(basegfx::fTools::less(aScale.getY(), 0.0));
     966             :     static bool bForceToOwnTransformer(false);
     967             : 
     968        4214 :     if(!bForceToOwnTransformer && !bRotated && !bSheared && !bMirroredX && !bMirroredY)
     969             :     {
     970             :         // with no rotation, shear or mirroring it can be mapped to DrawBitmapEx
     971             :         // do *not* execute the mirroring here, it's done in the fallback
     972             :         // #i124580# the correct DestSize needs to be calculated based on MaxXY values
     973        4178 :         const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
     974             :         const Size aDestSize(
     975        8356 :             basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
     976       12534 :             basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
     977             : 
     978        4178 :         DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
     979        4178 :         return;
     980             :     }
     981             : 
     982             :     // we have rotation,shear or mirror, check if some crazy mode needs the
     983             :     // created transformed bitmap
     984          36 :     const bool bInvert(ROP_INVERT == meRasterOp);
     985          36 :     const bool bBitmapChangedColor(mnDrawMode & (DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP));
     986          36 :     const bool bMetafile(mpMetaFile);
     987          36 :     bool bDone(false);
     988          70 :     const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
     989          36 :     const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile );
     990             : 
     991          36 :     if(!bForceToOwnTransformer && bTryDirectPaint)
     992             :     {
     993          34 :         bDone = DrawTransformBitmapExDirect(aFullTransform, rBitmapEx);
     994             :     }
     995             : 
     996          36 :     if(!bDone)
     997             :     {
     998             :         // take the fallback when no rotate and shear, but mirror (else we would have done this above)
     999          36 :         if(!bForceToOwnTransformer && !bRotated && !bSheared)
    1000             :         {
    1001             :             // with no rotation or shear it can be mapped to DrawBitmapEx
    1002             :             // do *not* execute the mirroring here, it's done in the fallback
    1003             :             // #i124580# the correct DestSize needs to be calculated based on MaxXY values
    1004           2 :             const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
    1005             :             const Size aDestSize(
    1006           4 :                 basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
    1007           6 :                 basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
    1008             : 
    1009           2 :             DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
    1010           2 :             return;
    1011             :         }
    1012             : 
    1013             :         // fallback; create transformed bitmap the hard way (back-transform
    1014             :         // the pixels) and paint
    1015          34 :         basegfx::B2DRange aVisibleRange(0.0, 0.0, 1.0, 1.0);
    1016             : 
    1017             :         // limit maximum area to something looking good for non-pixel-based targets (metafile, printer)
    1018             :         // by using a fixed minimum (allow at least, but no need to utilize) for good smooting and an area
    1019             :         // dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
    1020             :         // to avoid crashes/ressource problems (ca. 1500x3000 here)
    1021          34 :         const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel());
    1022          34 :         const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
    1023          34 :         const double fOrigAreaScaled(bSheared || bRotated ? fOrigArea * 1.44 : fOrigArea);
    1024          34 :         double fMaximumArea(std::min(4500000.0, std::max(1000000.0, fOrigAreaScaled)));
    1025             : 
    1026          34 :         if(!bMetafile)
    1027             :         {
    1028          34 :             if ( !TransformAndReduceBitmapExToTargetRange( aFullTransform, aVisibleRange, fMaximumArea ) )
    1029           0 :                 return;
    1030             :         }
    1031             : 
    1032          34 :         if(!aVisibleRange.isEmpty())
    1033             :         {
    1034             :             static bool bDoSmoothAtAll(true);
    1035          34 :             BitmapEx aTransformed(rBitmapEx);
    1036             : 
    1037             :             // #122923# when the result needs an alpha channel due to being rotated or sheared
    1038             :             // and thus uncovering areas, add these channels so that the own transformer (used
    1039             :             // in getTransformed) also creates a transformed alpha channel
    1040          34 :             if(!aTransformed.IsTransparent() && (bSheared || bRotated))
    1041             :             {
    1042             :                 // parts will be uncovered, extend aTransformed with a mask bitmap
    1043           0 :                 const Bitmap aContent(aTransformed.GetBitmap());
    1044             : 
    1045           0 :                 AlphaMask aMaskBmp(aContent.GetSizePixel());
    1046           0 :                 aMaskBmp.Erase(0);
    1047             : 
    1048           0 :                 aTransformed = BitmapEx(aContent, aMaskBmp);
    1049             :             }
    1050             : 
    1051          68 :             aTransformed = aTransformed.getTransformed(
    1052             :                 aFullTransform,
    1053             :                 aVisibleRange,
    1054             :                 fMaximumArea,
    1055          34 :                 bDoSmoothAtAll);
    1056          34 :             basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
    1057             : 
    1058             :             // get logic object target range
    1059          34 :             aTargetRange.transform(rTransformation);
    1060             : 
    1061             :             // get from unified/relative VisibleRange to logoc one
    1062             :             aVisibleRange.transform(
    1063             :                 basegfx::tools::createScaleTranslateB2DHomMatrix(
    1064             :                     aTargetRange.getRange(),
    1065          34 :                     aTargetRange.getMinimum()));
    1066             : 
    1067             :             // extract point and size; do not remove size, the bitmap may have been prepared reduced by purpose
    1068             :             // #i124580# the correct DestSize needs to be calculated based on MaxXY values
    1069          34 :             const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY()));
    1070             :             const Size aDestSize(
    1071          68 :                 basegfx::fround(aVisibleRange.getMaxX()) - aDestPt.X(),
    1072         102 :                 basegfx::fround(aVisibleRange.getMaxY()) - aDestPt.Y());
    1073             : 
    1074          34 :             DrawBitmapEx(aDestPt, aDestSize, aTransformed);
    1075             :         }
    1076          34 :     }
    1077             : }
    1078             : 
    1079             : namespace
    1080             : {
    1081           4 :     BitmapEx makeDisabledBitmap(const Bitmap &rBitmap)
    1082             :     {
    1083           4 :         const Size aTotalSize( rBitmap.GetSizePixel() );
    1084           4 :         Bitmap aGrey( aTotalSize, 8, &Bitmap::GetGreyPalette( 256 ) );
    1085           8 :         AlphaMask aGreyAlphaMask( aTotalSize );
    1086           4 :         BitmapReadAccess*  pBmp = const_cast<Bitmap&>(rBitmap).AcquireReadAccess();
    1087           4 :         BitmapWriteAccess* pGrey = aGrey.AcquireWriteAccess();
    1088           4 :         BitmapWriteAccess* pGreyAlphaMask = aGreyAlphaMask.AcquireWriteAccess();
    1089             : 
    1090           4 :         if( pBmp && pGrey && pGreyAlphaMask )
    1091             :         {
    1092           4 :             BitmapColor aGreyVal( 0 );
    1093           8 :             BitmapColor aGreyAlphaMaskVal( 0 );
    1094           4 :             const int nLeft = 0, nRight = aTotalSize.Width();
    1095           4 :             const int nTop = 0, nBottom = nTop + aTotalSize.Height();
    1096             : 
    1097          68 :             for( int nY = nTop; nY < nBottom; ++nY )
    1098             :             {
    1099        1088 :                 for( int nX = nLeft; nX < nRight; ++nX )
    1100             :                 {
    1101        1024 :                     aGreyVal.SetIndex( pBmp->GetLuminance( nY, nX ) );
    1102        1024 :                     pGrey->SetPixel( nY, nX, aGreyVal );
    1103             : 
    1104        1024 :                     aGreyAlphaMaskVal.SetIndex( static_cast< sal_uInt8 >( 128ul ) );
    1105        1024 :                     pGreyAlphaMask->SetPixel( nY, nX, aGreyAlphaMaskVal );
    1106             :                 }
    1107           4 :             }
    1108             :         }
    1109             : 
    1110           4 :         const_cast<Bitmap&>(rBitmap).ReleaseAccess( pBmp );
    1111           4 :         aGrey.ReleaseAccess( pGrey );
    1112           4 :         aGreyAlphaMask.ReleaseAccess( pGreyAlphaMask );
    1113           8 :         return BitmapEx( aGrey, aGreyAlphaMask );
    1114             :     }
    1115             : }
    1116             : 
    1117      183822 : void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle )
    1118             : {
    1119      183822 :     DrawImage( rPos, Size(), rImage, nStyle );
    1120      183822 : }
    1121             : 
    1122      190808 : void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
    1123             :                               const Image& rImage, sal_uInt16 nStyle )
    1124             : {
    1125      190808 :     bool bIsSizeValid = (rSize.getWidth() == 0 || rSize.getHeight() == 0) ? false : true;
    1126             : 
    1127      190808 :     if( rImage.mpImplData && !ImplIsRecordLayout() )
    1128             :     {
    1129      187528 :         switch( rImage.mpImplData->meType )
    1130             :         {
    1131             :             case IMAGETYPE_BITMAP:
    1132             :             {
    1133        5575 :                 const Bitmap &rBitmap = *static_cast< Bitmap* >( rImage.mpImplData->mpData );
    1134        5575 :                 if( nStyle & IMAGE_DRAW_DISABLE )
    1135             :                 {
    1136           4 :                     if ( bIsSizeValid )
    1137           0 :                         DrawBitmapEx( rPos, rSize, makeDisabledBitmap(rBitmap) );
    1138             :                     else
    1139           4 :                         DrawBitmapEx( rPos, makeDisabledBitmap(rBitmap) );
    1140             :                 }
    1141             :                 else
    1142             :                 {
    1143        5571 :                     if ( bIsSizeValid )
    1144           2 :                         DrawBitmap( rPos, rSize, rBitmap );
    1145             :                     else
    1146        5569 :                         DrawBitmap( rPos, rBitmap );
    1147             :                 }
    1148             :             }
    1149        5575 :             break;
    1150             : 
    1151             :             case IMAGETYPE_IMAGE:
    1152             :             {
    1153      181953 :                 ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
    1154             : 
    1155      181953 :                 if ( !pData->mpImageBitmap )
    1156             :                 {
    1157       87883 :                     const Size aSize( pData->maBmpEx.GetSizePixel() );
    1158             : 
    1159       87883 :                     pData->mpImageBitmap = new ImplImageBmp;
    1160       87883 :                     pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
    1161             :                 }
    1162             : 
    1163      181953 :                 if ( bIsSizeValid )
    1164        6984 :                     pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
    1165             :                 else
    1166      174969 :                     pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
    1167             :             }
    1168      181953 :             break;
    1169             : 
    1170             :             default:
    1171           0 :             break;
    1172             :         }
    1173             :     }
    1174      190808 : }
    1175             : 
    1176             : namespace
    1177             : {
    1178             :     // Co = Cs + Cd*(1-As) premultiplied alpha -or-
    1179             :     // Co = (AsCs + AdCd*(1-As)) / Ao
    1180      108405 :     inline sal_uInt8 CalcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceAlpha,
    1181             :                                 const sal_uInt8 nDstAlpha, const sal_uInt8 nResAlpha, const sal_uInt8 nDestColor )
    1182             :     {
    1183      216810 :         int c = nResAlpha ? ( (int)nSourceAlpha*nSourceColor + (int)nDstAlpha*nDestColor -
    1184      325215 :                               (int)nDstAlpha*nDestColor*nSourceAlpha/255 ) / (int)nResAlpha : 0;
    1185      108405 :         return sal_uInt8( c );
    1186             :     }
    1187             : 
    1188       36135 :     inline BitmapColor AlphaBlend( int nX,               int nY,
    1189             :                                    const long            nMapX,
    1190             :                                    const long            nMapY,
    1191             :                                    BitmapReadAccess*     pP,
    1192             :                                    BitmapReadAccess*     pA,
    1193             :                                    BitmapReadAccess*     pB,
    1194             :                                    BitmapWriteAccess*    pAlphaW,
    1195             :                                    sal_uInt8&            nResAlpha )
    1196             :     {
    1197       72270 :         BitmapColor aDstCol,aSrcCol;
    1198       36135 :         aSrcCol = pP->GetColor( nMapY, nMapX );
    1199       36135 :         aDstCol = pB->GetColor( nY, nX );
    1200             : 
    1201             :         // vcl stores transparency, not alpha - invert it
    1202       36135 :         const sal_uInt8 nSrcAlpha = 255 - pA->GetPixelIndex( nMapY, nMapX );
    1203       36135 :         const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixelIndex( nY, nX );
    1204             : 
    1205             :         // Perform porter-duff compositing 'over' operation
    1206             : 
    1207             :         // Co = Cs + Cd*(1-As)
    1208             :         // Ad = As + Ad*(1-As)
    1209       36135 :         nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255;
    1210             : 
    1211       36135 :         aDstCol.SetRed( CalcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) );
    1212       36135 :         aDstCol.SetBlue( CalcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) );
    1213       36135 :         aDstCol.SetGreen( CalcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) );
    1214             : 
    1215       72270 :         return aDstCol;
    1216             :     }
    1217             : }
    1218             : 
    1219          75 : Bitmap OutputDevice::BlendBitmapWithAlpha(
    1220             :             Bitmap&             aBmp,
    1221             :             BitmapReadAccess*   pP,
    1222             :             BitmapReadAccess*   pA,
    1223             :             const Rectangle&    aDstRect,
    1224             :             const sal_Int32     nOffY,
    1225             :             const sal_Int32     nDstHeight,
    1226             :             const sal_Int32     nOffX,
    1227             :             const sal_Int32     nDstWidth,
    1228             :             const long*         pMapX,
    1229             :             const long*         pMapY )
    1230             : 
    1231             : {
    1232          75 :     BitmapColor aDstCol;
    1233          75 :     Bitmap      res;
    1234             :     int         nX, nY;
    1235             :     sal_uInt8   nResAlpha;
    1236             : 
    1237             :     SAL_WARN_IF( !mpAlphaVDev, "vcl.gdi", "BlendBitmapWithAlpha(): call me only with valid alpha VirtualDevice!" );
    1238             : 
    1239          75 :     bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
    1240          75 :     mpAlphaVDev->EnableMapMode(false);
    1241             : 
    1242         150 :     Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
    1243          75 :     BitmapWriteAccess*  pAlphaW = aAlphaBitmap.AcquireWriteAccess();
    1244             : 
    1245          75 :     if( GetBitCount() <= 8 )
    1246             :     {
    1247           0 :         Bitmap              aDither( aBmp.GetSizePixel(), 8 );
    1248           0 :         BitmapColor         aIndex( 0 );
    1249           0 :         BitmapReadAccess*   pB = aBmp.AcquireReadAccess();
    1250           0 :         BitmapWriteAccess*  pW = aDither.AcquireWriteAccess();
    1251             : 
    1252           0 :         if (pB && pP && pA && pW && pAlphaW)
    1253             :         {
    1254             :             int nOutY;
    1255             : 
    1256           0 :             for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
    1257             :             {
    1258           0 :                 const long nMapY = pMapY[ nY ];
    1259           0 :                 const long nModY = ( nOutY & 0x0FL ) << 4L;
    1260             :                 int nOutX;
    1261             : 
    1262           0 :                 for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
    1263             :                 {
    1264           0 :                     const long  nMapX = pMapX[ nX ];
    1265           0 :                     const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
    1266             : 
    1267           0 :                     aDstCol = AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha );
    1268             : 
    1269           0 :                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
    1270           0 :                                               nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
    1271           0 :                                               nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
    1272           0 :                     pW->SetPixel( nY, nX, aIndex );
    1273             : 
    1274           0 :                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] +
    1275           0 :                                                    nVCLGLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] +
    1276           0 :                                                    nVCLBLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] ) );
    1277           0 :                     pAlphaW->SetPixel( nY, nX, aIndex );
    1278             :                 }
    1279             :             }
    1280             :         }
    1281             : 
    1282           0 :         aBmp.ReleaseAccess( pB );
    1283           0 :         aDither.ReleaseAccess( pW );
    1284           0 :         res = aDither;
    1285             :     }
    1286             :     else
    1287             :     {
    1288          75 :         BitmapWriteAccess*  pB = aBmp.AcquireWriteAccess();
    1289          75 :         if (pB && pP && pA && pAlphaW)
    1290             :         {
    1291        1756 :             for( nY = 0; nY < nDstHeight; nY++ )
    1292             :             {
    1293        1681 :                 const long  nMapY = pMapY[ nY ];
    1294             : 
    1295       37816 :                 for( nX = 0; nX < nDstWidth; nX++ )
    1296             :                 {
    1297       36135 :                     const long nMapX = pMapX[ nX ];
    1298       36135 :                     aDstCol = AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha );
    1299             : 
    1300       36135 :                     pB->SetPixel( nY, nX, aDstCol );
    1301       36135 :                     pAlphaW->SetPixel( nY, nX, Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha) );
    1302             :                 }
    1303             :             }
    1304             :         }
    1305             : 
    1306          75 :         aBmp.ReleaseAccess( pB );
    1307          75 :         res = aBmp;
    1308             :     }
    1309             : 
    1310          75 :     aAlphaBitmap.ReleaseAccess( pAlphaW );
    1311          75 :     mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap );
    1312          75 :     mpAlphaVDev->EnableMapMode( bOldMapMode );
    1313             : 
    1314         150 :     return res;
    1315             : }
    1316             : 
    1317      211632 : Bitmap OutputDevice::BlendBitmap(
    1318             :             Bitmap&             aBmp,
    1319             :             BitmapReadAccess*   pP,
    1320             :             BitmapReadAccess*   pA,
    1321             :             const sal_Int32     nOffY,
    1322             :             const sal_Int32     nDstHeight,
    1323             :             const sal_Int32     nOffX,
    1324             :             const sal_Int32     nDstWidth,
    1325             :             const Rectangle&    aBmpRect,
    1326             :             const Size&         aOutSz,
    1327             :             const bool          bHMirr,
    1328             :             const bool          bVMirr,
    1329             :             const long*         pMapX,
    1330             :             const long*         pMapY )
    1331             : {
    1332      211632 :     BitmapColor aDstCol;
    1333      211632 :     Bitmap      res;
    1334             :     int         nX, nY;
    1335             : 
    1336      211632 :     if( GetBitCount() <= 8 )
    1337             :     {
    1338           0 :         Bitmap              aDither( aBmp.GetSizePixel(), 8 );
    1339           0 :         BitmapColor         aIndex( 0 );
    1340           0 :         BitmapReadAccess*   pB = aBmp.AcquireReadAccess();
    1341           0 :         BitmapWriteAccess*  pW = aDither.AcquireWriteAccess();
    1342             : 
    1343           0 :         if( pB && pP && pA && pW )
    1344             :         {
    1345             :             int nOutY;
    1346             : 
    1347           0 :             for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
    1348             :             {
    1349           0 :                 const long nMapY = pMapY[ nY ];
    1350           0 :                 const long nModY = ( nOutY & 0x0FL ) << 4L;
    1351             :                 int nOutX;
    1352             : 
    1353           0 :                 for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
    1354             :                 {
    1355           0 :                     const long  nMapX = pMapX[ nX ];
    1356           0 :                     const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
    1357             : 
    1358           0 :                     aDstCol = pB->GetColor( nY, nX );
    1359           0 :                     aDstCol.Merge( pP->GetColor( nMapY, nMapX ), pA->GetPixelIndex( nMapY, nMapX ) );
    1360           0 :                     aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
    1361           0 :                                               nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
    1362           0 :                                               nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
    1363           0 :                     pW->SetPixel( nY, nX, aIndex );
    1364             :                 }
    1365             :             }
    1366             :         }
    1367             : 
    1368           0 :         aBmp.ReleaseAccess( pB );
    1369           0 :         aDither.ReleaseAccess( pW );
    1370           0 :         res = aDither;
    1371             :     }
    1372             :     else
    1373             :     {
    1374      211632 :         BitmapWriteAccess*  pB = aBmp.AcquireWriteAccess();
    1375             : 
    1376      211632 :         bool bFastBlend = false;
    1377      211632 :         if( pP && pA && pB )
    1378             :         {
    1379             :             SalTwoRect aTR;
    1380      211632 :             aTR.mnSrcX      = aBmpRect.Left();
    1381      211632 :             aTR.mnSrcY      = aBmpRect.Top();
    1382      211632 :             aTR.mnSrcWidth  = aBmpRect.GetWidth();
    1383      211632 :             aTR.mnSrcHeight = aBmpRect.GetHeight();
    1384      211632 :             aTR.mnDestX     = nOffX;
    1385      211632 :             aTR.mnDestY     = nOffY;
    1386      211632 :             aTR.mnDestWidth = aOutSz.Width();
    1387      211632 :             aTR.mnDestHeight= aOutSz.Height();
    1388             : 
    1389      211632 :             if( !bHMirr && !bVMirr )
    1390      211632 :                 bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR );
    1391             :         }
    1392             : 
    1393      211632 :         if( pP && pA && pB && !bFastBlend )
    1394             :         {
    1395      120942 :             switch( pP->GetScanlineFormat() )
    1396             :             {
    1397             :                 case( BMP_FORMAT_8BIT_PAL ):
    1398             :                     {
    1399     1706284 :                         for( nY = 0; nY < nDstHeight; nY++ )
    1400             :                         {
    1401     1612113 :                             const long  nMapY = pMapY[ nY ];
    1402     1612113 :                             Scanline    pPScan = pP->GetScanline( nMapY );
    1403     1612113 :                             Scanline    pAScan = pA->GetScanline( nMapY );
    1404             : 
    1405    26980115 :                             for( nX = 0; nX < nDstWidth; nX++ )
    1406             :                             {
    1407    25368002 :                                 const long nMapX = pMapX[ nX ];
    1408    25368002 :                                 aDstCol = pB->GetPixel( nY, nX );
    1409    25368002 :                                 pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
    1410    50736004 :                                                                      pAScan[ nMapX ] ) );
    1411             :                             }
    1412             :                         }
    1413             :                     }
    1414       94171 :                     break;
    1415             : 
    1416             :                 case( BMP_FORMAT_24BIT_TC_BGR ):
    1417             :                     {
    1418     4264764 :                         for( nY = 0; nY < nDstHeight; nY++ )
    1419             :                         {
    1420     4237993 :                             const long  nMapY = pMapY[ nY ];
    1421     4237993 :                             Scanline    pPScan = pP->GetScanline( nMapY );
    1422     4237993 :                             Scanline    pAScan = pA->GetScanline( nMapY );
    1423             : 
    1424   144988936 :                             for( nX = 0; nX < nDstWidth; nX++ )
    1425             :                             {
    1426   140750943 :                                 const long  nMapX = pMapX[ nX ];
    1427   140750943 :                                 Scanline    pTmp = pPScan + nMapX * 3;
    1428             : 
    1429   140750943 :                                 aDstCol = pB->GetPixel( nY, nX );
    1430   422252829 :                                 pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
    1431   563003772 :                                                                      pAScan[ nMapX ] ) );
    1432             :                             }
    1433             :                         }
    1434             :                     }
    1435       26771 :                     break;
    1436             : 
    1437             :                 case( BMP_FORMAT_24BIT_TC_RGB ):
    1438             :                     {
    1439           0 :                         for( nY = 0; nY < nDstHeight; nY++ )
    1440             :                         {
    1441           0 :                             const long  nMapY = pMapY[ nY ];
    1442           0 :                             Scanline    pPScan = pP->GetScanline( nMapY );
    1443           0 :                             Scanline    pAScan = pA->GetScanline( nMapY );
    1444             : 
    1445           0 :                             for( nX = 0; nX < nDstWidth; nX++ )
    1446             :                             {
    1447           0 :                                 const long  nMapX = pMapX[ nX ];
    1448           0 :                                 Scanline    pTmp = pPScan + nMapX * 3;
    1449             : 
    1450           0 :                                 aDstCol = pB->GetPixel( nY, nX );
    1451           0 :                                 pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
    1452           0 :                                                                      pAScan[ nMapX ] ) );
    1453             :                             }
    1454             :                         }
    1455             :                     }
    1456           0 :                     break;
    1457             : 
    1458             :                 default:
    1459             :                 {
    1460           0 :                     for( nY = 0; nY < nDstHeight; nY++ )
    1461             :                     {
    1462           0 :                         const long  nMapY = pMapY[ nY ];
    1463           0 :                         Scanline    pAScan = pA->GetScanline( nMapY );
    1464             : 
    1465           0 :                         for( nX = 0; nX < nDstWidth; nX++ )
    1466             :                         {
    1467           0 :                             const long nMapX = pMapX[ nX ];
    1468           0 :                             aDstCol = pB->GetPixel( nY, nX );
    1469             :                             pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
    1470           0 :                                                                  pAScan[ nMapX ] ) );
    1471             :                         }
    1472             :                     }
    1473             :                 }
    1474           0 :                 break;
    1475             :             }
    1476             :         }
    1477             : 
    1478      211632 :         aBmp.ReleaseAccess( pB );
    1479      211632 :         res = aBmp;
    1480             :     }
    1481             : 
    1482      211632 :     return res;
    1483        1233 : }
    1484             : 
    1485             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10