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

Generated by: LCOV version 1.11