LCOV - code coverage report
Current view: top level - libreoffice/svtools/source/graphic - grfmgr2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 334 856 39.0 %
Date: 2012-12-27 Functions: 15 29 51.7 %
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/bmpacc.hxx>
      21             : #include <tools/poly.hxx>
      22             : #include <vcl/outdev.hxx>
      23             : #include <vcl/window.hxx>
      24             : #include <vcl/gdimtf.hxx>
      25             : #include <vcl/metaact.hxx>
      26             : #include <vcl/metric.hxx>
      27             : #include <vcl/animate.hxx>
      28             : #include <vcl/alpha.hxx>
      29             : #include <vcl/virdev.hxx>
      30             : #include "grfcache.hxx"
      31             : #include <svtools/grfmgr.hxx>
      32             : 
      33             : // -----------
      34             : // - defines -
      35             : // -----------
      36             : 
      37             : #define WATERMARK_LUM_OFFSET        50
      38             : #define WATERMARK_CON_OFFSET        -70
      39             : #define MAP( cVal0, cVal1, nFrac )  ((sal_uInt8)((((long)(cVal0)<<20L)+nFrac*((long)(cVal1)-(cVal0)))>>20L))
      40             : 
      41             : // ------------------
      42             : // - GraphicManager -
      43             : // ------------------
      44             : 
      45          18 : GraphicManager::GraphicManager( sal_uLong nCacheSize, sal_uLong nMaxObjCacheSize ) :
      46          18 :         mpCache( new GraphicCache( nCacheSize, nMaxObjCacheSize ) )
      47             : {
      48          18 : }
      49             : 
      50           4 : GraphicManager::~GraphicManager()
      51             : {
      52           2 :     for( size_t i = 0, n = maObjList.size(); i < n; ++i )
      53           0 :         maObjList[ i ]->GraphicManagerDestroyed();
      54             : 
      55           2 :     delete mpCache;
      56           2 : }
      57             : 
      58           0 : void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize )
      59             : {
      60           0 :     mpCache->SetMaxDisplayCacheSize( nNewCacheSize );
      61           0 : }
      62             : 
      63           0 : void GraphicManager::SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, sal_Bool bDestroyGreaterCached )
      64             : {
      65           0 :     mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached );
      66           0 : }
      67             : 
      68          18 : void GraphicManager::SetCacheTimeout( sal_uLong nTimeoutSeconds )
      69             : {
      70          18 :     mpCache->SetCacheTimeout( nTimeoutSeconds );
      71          18 : }
      72             : 
      73           0 : void GraphicManager::ReleaseFromCache( const GraphicObject& /*rObj*/ )
      74             : {
      75             :     // !!!
      76           0 : }
      77             : 
      78          16 : sal_Bool GraphicManager::IsInCache( OutputDevice* pOut, const Point& rPt,
      79             :                                     const Size& rSz, const GraphicObject& rObj,
      80             :                                     const GraphicAttr& rAttr ) const
      81             : {
      82          16 :     return mpCache->IsInDisplayCache( pOut, rPt, rSz, rObj, rAttr );
      83             : }
      84             : 
      85          24 : sal_Bool GraphicManager::DrawObj( OutputDevice* pOut, const Point& rPt, const Size& rSz,
      86             :                               GraphicObject& rObj, const GraphicAttr& rAttr,
      87             :                               const sal_uLong nFlags, sal_Bool& rCached )
      88             : {
      89          24 :     Point   aPt( rPt );
      90          24 :     Size    aSz( rSz );
      91          24 :     sal_Bool    bRet = sal_False;
      92             : 
      93          24 :     rCached = sal_False;
      94             : 
      95          24 :     if( ( rObj.GetType() == GRAPHIC_BITMAP ) || ( rObj.GetType() == GRAPHIC_GDIMETAFILE ) )
      96             :     {
      97             :         // create output and fill cache
      98             : 
      99         104 :         if( rObj.IsAnimated() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) ||
     100          24 :             ( !( nFlags & GRFMGR_DRAW_NO_SUBSTITUTE ) &&
     101             :               ( ( nFlags & GRFMGR_DRAW_SUBSTITUTE ) ||
     102          24 :                 !( nFlags & GRFMGR_DRAW_CACHED ) ||
     103          32 :                 ( pOut->GetConnectMetaFile() && !pOut->IsOutputEnabled() ) ) ) )
     104             :         {
     105             :             // simple output of transformed graphic
     106           8 :             const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) );
     107             : 
     108           8 :             if( aGraphic.IsSupportedGraphic() )
     109             :             {
     110           8 :                 const sal_uInt16 nRot10 = rAttr.GetRotation() % 3600;
     111             : 
     112           8 :                 if( nRot10 )
     113             :                 {
     114           0 :                     Polygon aPoly( Rectangle( aPt, aSz ) );
     115             : 
     116           0 :                     aPoly.Rotate( aPt, nRot10 );
     117           0 :                     const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
     118           0 :                     aPt = aRotBoundRect.TopLeft();
     119           0 :                     aSz = aRotBoundRect.GetSize();
     120             :                 }
     121             : 
     122           8 :                 aGraphic.Draw( pOut, aPt, aSz );
     123             :             }
     124             : 
     125           8 :             bRet = sal_True;
     126             :         }
     127             : 
     128          24 :         if( !bRet )
     129             :         {
     130             :             // cached/direct drawing
     131          16 :             if( !mpCache->DrawDisplayCacheObj( pOut, aPt, aSz, rObj, rAttr ) )
     132           8 :                 bRet = ImplDraw( pOut, aPt, aSz, rObj, rAttr, nFlags, rCached );
     133             :             else
     134           8 :                 bRet = rCached = sal_True;
     135             :         }
     136             :     }
     137             : 
     138          24 :     return bRet;
     139             : }
     140             : 
     141        2019 : void GraphicManager::ImplRegisterObj( const GraphicObject& rObj, Graphic& rSubstitute,
     142             :                                       const rtl::OString* pID, const GraphicObject* pCopyObj )
     143             : {
     144        2019 :     maObjList.push_back( (GraphicObject*)&rObj );
     145        2019 :     mpCache->AddGraphicObject( rObj, rSubstitute, pID, pCopyObj );
     146        2019 : }
     147             : 
     148        1768 : void GraphicManager::ImplUnregisterObj( const GraphicObject& rObj )
     149             : {
     150        1768 :     mpCache->ReleaseGraphicObject( rObj );
     151       33837 :     for( GraphicObjectList_impl::iterator it = maObjList.begin(); it != maObjList.end(); ++it )
     152             :     {
     153       33837 :         if ( *it == &rObj ) {
     154        1768 :             maObjList.erase( it );
     155        1768 :             break;
     156             :         }
     157             :     }
     158        1768 : }
     159             : 
     160          13 : void GraphicManager::ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj )
     161             : {
     162          13 :     mpCache->GraphicObjectWasSwappedOut( rObj );
     163          13 : }
     164             : 
     165         132 : rtl::OString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const
     166             : {
     167         132 :     return mpCache->GetUniqueID( rObj );
     168             : }
     169             : 
     170           0 : sal_Bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
     171             : {
     172           0 :     return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) );
     173             : }
     174             : 
     175           0 : void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj )
     176             : {
     177           0 :     mpCache->GraphicObjectWasSwappedIn( rObj );
     178           0 : }
     179             : 
     180           8 : sal_Bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt,
     181             :                                const Size& rSz, GraphicObject& rObj,
     182             :                                const GraphicAttr& rAttr,
     183             :                                const sal_uLong nFlags, sal_Bool& rCached )
     184             : {
     185           8 :     const Graphic&  rGraphic = rObj.GetGraphic();
     186           8 :     sal_Bool            bRet = sal_False;
     187             : 
     188           8 :     if( rGraphic.IsSupportedGraphic() && !rGraphic.IsSwapOut() )
     189             :     {
     190           8 :         if( GRAPHIC_BITMAP == rGraphic.GetType() )
     191             :         {
     192           7 :             const BitmapEx aSrcBmpEx( rGraphic.GetBitmapEx() );
     193             : 
     194             :             // #i46805# No point in caching a bitmap that is rendered
     195             :             // via RectFill on the OutDev
     196          14 :             if( !(pOut->GetDrawMode() & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP )) &&
     197           7 :                 mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) )
     198             :             {
     199           7 :                 BitmapEx aDstBmpEx;
     200             : 
     201           7 :                 if( ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags, &aDstBmpEx ) )
     202             :                 {
     203           7 :                     rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx );
     204           7 :                     bRet = sal_True;
     205           7 :                 }
     206             :             }
     207             : 
     208           7 :             if( !bRet )
     209           0 :                 bRet = ImplCreateOutput( pOut, rPt, rSz, aSrcBmpEx, rAttr, nFlags );
     210             :         }
     211             :         else
     212             :         {
     213           1 :             const GDIMetaFile& rSrcMtf = rGraphic.GetGDIMetaFile();
     214             : 
     215           1 :             if( mpCache->IsDisplayCacheable( pOut, rPt, rSz, rObj, rAttr ) )
     216             :             {
     217           1 :                 GDIMetaFile aDstMtf;
     218           1 :                 BitmapEx    aContainedBmpEx;
     219             : 
     220           1 :                 if( ImplCreateOutput( pOut, rPt, rSz, rSrcMtf, rAttr, nFlags, aDstMtf, aContainedBmpEx ) )
     221             :                 {
     222           1 :                     if( !!aContainedBmpEx )
     223             :                     {
     224             :                         // Use bitmap output method, if metafile basically contains only a single
     225             :                         // bitmap (allows caching the resulting pixmap).
     226           0 :                         BitmapEx aDstBmpEx;
     227             : 
     228           0 :                         if( ImplCreateOutput( pOut, rPt, rSz, aContainedBmpEx, rAttr, nFlags, &aDstBmpEx ) )
     229             :                         {
     230           0 :                             rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstBmpEx );
     231           0 :                             bRet = sal_True;
     232           0 :                         }
     233             :                     }
     234             :                     else
     235             :                     {
     236           1 :                         rCached = mpCache->CreateDisplayCacheObj( pOut, rPt, rSz, rObj, rAttr, aDstMtf );
     237           1 :                         bRet = sal_True;
     238             :                     }
     239           1 :                 }
     240             :             }
     241             : 
     242           1 :             if( !bRet )
     243             :             {
     244           0 :                 const Graphic aGraphic( rObj.GetTransformedGraphic( &rAttr ) );
     245             : 
     246           0 :                 if( aGraphic.IsSupportedGraphic() )
     247             :                 {
     248           0 :                     aGraphic.Draw( pOut, rPt, rSz );
     249           0 :                     bRet = sal_True;
     250           0 :                 }
     251             :             }
     252             :         }
     253             :     }
     254             : 
     255           8 :     return bRet;
     256             : }
     257             : 
     258           4 : sal_Bool ImplCreateRotatedScaled( const BitmapEx& rBmpEx, const GraphicAttr& rAttributes,
     259             :                                 sal_uInt16 nRot10, const Size& rUnrotatedSzPix,
     260             :                                 long nStartX, long nEndX, long nStartY, long nEndY,
     261             :                                 BitmapEx& rOutBmpEx )
     262             : {
     263           4 :     const long  aUnrotatedWidth  = rUnrotatedSzPix.Width();
     264           4 :     const long  aUnrotatedHeight = rUnrotatedSzPix.Height();
     265           4 :     const long  aBitmapWidth  = rBmpEx.GetSizePixel().Width();
     266           4 :     const long  aBitmapHeight = rBmpEx.GetSizePixel().Height();
     267             : 
     268             :     long    nX, nY, nTmpX, nTmpY, nTmpFX, nTmpFY, nTmp;
     269             :     double  fTmp;
     270             : 
     271           4 :     bool    bHMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0;
     272           4 :     bool    bVMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0;
     273             : 
     274           4 :     long*   pMapIX = new long[ aUnrotatedWidth ];
     275           4 :     long*   pMapFX = new long[ aUnrotatedWidth ];
     276           4 :     long*   pMapIY = new long[ aUnrotatedHeight ];
     277           4 :     long*   pMapFY = new long[ aUnrotatedHeight ];
     278             : 
     279           4 :     const double fScaleX = ( aUnrotatedWidth  - 1 ) / (double) ( aBitmapWidth  - 1 );
     280           4 :     const double fScaleY = ( aUnrotatedHeight - 1 ) / (double) ( aBitmapHeight - 1 );
     281             : 
     282           4 :     const double fRevScaleX = 1.0 / fScaleX;
     283           4 :     const double fRevScaleY = 1.0 / fScaleY;
     284             : 
     285             :     int x,y;
     286             : 
     287             :     // create horizontal mapping table
     288         878 :     for( x = 0, nTmpX = aBitmapWidth - 1L, nTmp = aBitmapWidth - 2L; x < aUnrotatedWidth; x++ )
     289             :     {
     290         874 :         fTmp = x * fRevScaleX;
     291             : 
     292         874 :         if( bHMirr )
     293           0 :             fTmp = nTmpX - fTmp;
     294             : 
     295         874 :         pMapIX[ x ] = MinMax( fTmp, 0, nTmp );
     296         874 :         pMapFX[ x ] = (long) ( ( fTmp - pMapIX[ x ] ) * 1048576.0 );
     297             :     }
     298             : 
     299             :     // create vertical mapping table
     300         230 :     for( y = 0, nTmpY = aBitmapHeight - 1L, nTmp = aBitmapHeight - 2L; y < aUnrotatedHeight; y++ )
     301             :     {
     302         226 :         fTmp = y * fRevScaleY;
     303             : 
     304         226 :         if( bVMirr )
     305           0 :             fTmp = nTmpY - fTmp;
     306             : 
     307         226 :         pMapIY[ y ] = MinMax( fTmp, 0, nTmp );
     308         226 :         pMapFY[ y ] = (long) ( ( fTmp - pMapIY[ y ] ) * 1048576.0 );
     309             :     }
     310             : 
     311             : 
     312           4 :     Bitmap              aBmp( rBmpEx.GetBitmap() );
     313           4 :     Bitmap              aOutBmp;
     314           4 :     BitmapReadAccess*   pReadAccess = aBmp.AcquireReadAccess();
     315             :     BitmapWriteAccess*  pWriteAccess;
     316             : 
     317           4 :     const double        fCosAngle = cos( nRot10 * F_PI1800 );
     318           4 :     const double        fSinAngle = sin( nRot10 * F_PI1800 );
     319           4 :     const long          aTargetWidth  = nEndX - nStartX + 1L;
     320           4 :     const long          aTargetHeight = nEndY - nStartY + 1L;
     321           4 :     long*               pCosX = new long[ aTargetWidth ];
     322           4 :     long*               pSinX = new long[ aTargetWidth ];
     323           4 :     long*               pCosY = new long[ aTargetHeight ];
     324           4 :     long*               pSinY = new long[ aTargetHeight ];
     325             :     long                nUnRotX, nUnRotY, nSinY, nCosY;
     326             :     sal_uInt8           cR0, cG0, cB0, cR1, cG1, cB1;
     327           4 :     bool                bRet = false;
     328             : 
     329           4 :     Polygon             aPoly( Rectangle( Point(), rUnrotatedSzPix ) );
     330           4 :     aPoly.Rotate( Point(), nRot10 );
     331           4 :     Rectangle           aNewBound( aPoly.GetBoundRect() );
     332             : 
     333           4 :     bool                scaleByAveraging = fScaleX < 0.6 || fScaleY < 0.6;
     334             : 
     335             :     // create horizontal mapping table
     336         878 :     for( x = 0, nTmpX = aNewBound.Left() + nStartX; x < aTargetWidth; x++ )
     337             :     {
     338         874 :         pCosX[ x ] = FRound( fCosAngle * ( fTmp = nTmpX++ << 8 ) );
     339         874 :         pSinX[ x ] = FRound( fSinAngle * fTmp );
     340             :     }
     341             : 
     342             :     // create vertical mapping table
     343         230 :     for( y = 0, nTmpY = aNewBound.Top() + nStartY; y < aTargetHeight; y++ )
     344             :     {
     345         226 :         pCosY[ y ] = FRound( fCosAngle * ( fTmp = nTmpY++ << 8 ) );
     346         226 :         pSinY[ y ] = FRound( fSinAngle * fTmp );
     347             :     }
     348             : 
     349           4 :     if( pReadAccess )
     350             :     {
     351           4 :         aOutBmp = Bitmap( Size( aTargetWidth, aTargetHeight ), 24 );
     352           4 :         pWriteAccess = aOutBmp.AcquireWriteAccess();
     353             : 
     354           4 :         if( pWriteAccess )
     355             :         {
     356           4 :             BitmapColor aColRes;
     357             : 
     358           4 :             if ( !scaleByAveraging )
     359             :             {
     360           4 :                 if( pReadAccess->HasPalette() )
     361             :                 {
     362         131 :                     for( y = 0; y < aTargetHeight; y++ )
     363             :                     {
     364         129 :                         nSinY = pSinY[ y ];
     365         129 :                         nCosY = pCosY[ y ];
     366             : 
     367       68996 :                         for( x = 0; x < aTargetWidth; x++ )
     368             :                         {
     369       68867 :                             nUnRotX = ( pCosX[ x ] - nSinY ) >> 8;
     370       68867 :                             nUnRotY = ( pSinX[ x ] + nCosY ) >> 8;
     371             : 
     372       68867 :                             if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) &&
     373             :                                 ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) )
     374             :                             {
     375       68867 :                                 nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ];
     376       68867 :                                 nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
     377             : 
     378       68867 :                                 const BitmapColor& rCol0 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( nTmpY, nTmpX ) );
     379       68867 :                                 const BitmapColor& rCol1 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( nTmpY, ++nTmpX ) );
     380       68867 :                                 cR0 = MAP( rCol0.GetRed(), rCol1.GetRed(), nTmpFX );
     381       68867 :                                 cG0 = MAP( rCol0.GetGreen(), rCol1.GetGreen(), nTmpFX );
     382       68867 :                                 cB0 = MAP( rCol0.GetBlue(), rCol1.GetBlue(), nTmpFX );
     383             : 
     384       68867 :                                 const BitmapColor& rCol3 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( ++nTmpY, nTmpX ) );
     385       68867 :                                 const BitmapColor& rCol2 = pReadAccess->GetPaletteColor( pReadAccess->GetPixel( nTmpY, --nTmpX ) );
     386       68867 :                                 cR1 = MAP( rCol2.GetRed(), rCol3.GetRed(), nTmpFX );
     387       68867 :                                 cG1 = MAP( rCol2.GetGreen(), rCol3.GetGreen(), nTmpFX );
     388       68867 :                                 cB1 = MAP( rCol2.GetBlue(), rCol3.GetBlue(), nTmpFX );
     389             : 
     390       68867 :                                 aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
     391       68867 :                                 aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
     392       68867 :                                 aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
     393       68867 :                                 pWriteAccess->SetPixel( y, x, aColRes );
     394             :                             }
     395             :                         }
     396             :                     }
     397             :                 }
     398             :                 else
     399             :                 {
     400           2 :                     BitmapColor aCol0, aCol1;
     401             : 
     402          99 :                     for( y = 0; y < aTargetHeight; y++ )
     403             :                     {
     404          97 :                         nSinY = pSinY[ y ];
     405          97 :                         nCosY = pCosY[ y ];
     406             : 
     407        7561 :                         for( x = 0; x < aTargetWidth; x++ )
     408             :                         {
     409        7464 :                             nUnRotX = ( pCosX[ x ] - nSinY ) >> 8;
     410        7464 :                             nUnRotY = ( pSinX[ x ] + nCosY ) >> 8;
     411             : 
     412        7464 :                             if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) &&
     413             :                                 ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) )
     414             :                             {
     415        7464 :                                 nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ];
     416        7464 :                                 nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
     417             : 
     418        7464 :                                 aCol0 = pReadAccess->GetPixel( nTmpY, nTmpX );
     419        7464 :                                 aCol1 = pReadAccess->GetPixel( nTmpY, ++nTmpX );
     420        7464 :                                 cR0 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
     421        7464 :                                 cG0 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
     422        7464 :                                 cB0 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
     423             : 
     424        7464 :                                 aCol1 = pReadAccess->GetPixel( ++nTmpY, nTmpX );
     425        7464 :                                 aCol0 = pReadAccess->GetPixel( nTmpY, --nTmpX );
     426        7464 :                                 cR1 = MAP( aCol0.GetRed(), aCol1.GetRed(), nTmpFX );
     427        7464 :                                 cG1 = MAP( aCol0.GetGreen(), aCol1.GetGreen(), nTmpFX );
     428        7464 :                                 cB1 = MAP( aCol0.GetBlue(), aCol1.GetBlue(), nTmpFX );
     429             : 
     430        7464 :                                 aColRes.SetRed( MAP( cR0, cR1, nTmpFY ) );
     431        7464 :                                 aColRes.SetGreen( MAP( cG0, cG1, nTmpFY ) );
     432        7464 :                                 aColRes.SetBlue( MAP( cB0, cB1, nTmpFY ) );
     433        7464 :                                 pWriteAccess->SetPixel( y, x, aColRes );
     434             :                             }
     435             :                         }
     436           2 :                     }
     437             :                 }
     438             :             }
     439             :             else // scaleByAveraging
     440             :             {
     441             :                 double aSumRed, aSumGreen, aSumBlue, aCount;
     442           0 :                 BitmapColor aColor;
     443           0 :                 BitmapColor aResultColor;
     444             : 
     445           0 :                 for( y = 0; y < aTargetHeight; y++ )
     446             :                 {
     447           0 :                     nSinY = pSinY[ y ];
     448           0 :                     nCosY = pCosY[ y ];
     449             : 
     450           0 :                     for( x = 0; x < aTargetWidth; x++ )
     451             :                     {
     452           0 :                         double aUnrotatedX = ( pCosX[ x ] - nSinY ) / 256.0;
     453           0 :                         double aUnrotatedY = ( pSinX[ x ] + nCosY ) / 256.0;
     454             : 
     455           0 :                         if ( bHMirr )
     456           0 :                             aUnrotatedX = aUnrotatedWidth - aUnrotatedX - 1;
     457           0 :                         if ( bVMirr )
     458           0 :                             aUnrotatedY = aUnrotatedHeight - aUnrotatedY - 1;
     459             : 
     460           0 :                         if( ( aUnrotatedX >= 0 ) && ( aUnrotatedX < aUnrotatedWidth ) &&
     461             :                             ( aUnrotatedY >= 0 ) && ( aUnrotatedY < aUnrotatedHeight ) )
     462             :                         {
     463           0 :                             double dYStart = ((aUnrotatedY + 0.5) * fRevScaleY) - 0.5;
     464           0 :                             double dYEnd   = ((aUnrotatedY + 1.5) * fRevScaleY) - 0.5;
     465             : 
     466           0 :                             int yStart = MinMax( dYStart, 0, aBitmapHeight - 1);
     467           0 :                             int yEnd   = MinMax( dYEnd,   0, aBitmapHeight - 1);
     468             : 
     469           0 :                             double dXStart = ((aUnrotatedX + 0.5) * fRevScaleX) - 0.5;
     470           0 :                             double dXEnd   = ((aUnrotatedX + 1.5) * fRevScaleX) - 0.5;
     471             : 
     472           0 :                             int xStart = MinMax( dXStart, 0, aBitmapWidth - 1);
     473           0 :                             int xEnd   = MinMax( dXEnd,   0, aBitmapWidth - 1);
     474             : 
     475           0 :                             aSumRed = aSumGreen = aSumBlue = 0.0;
     476           0 :                             aCount = 0;
     477             : 
     478           0 :                             for (int yIn = yStart; yIn <= yEnd; yIn++)
     479             :                             {
     480           0 :                                 for (int xIn = xStart; xIn <= xEnd; xIn++)
     481             :                                 {
     482           0 :                                     aColor = pReadAccess->GetPixel( yIn, xIn );
     483             : 
     484           0 :                                     if( pReadAccess->HasPalette() )
     485           0 :                                         aColor = pReadAccess->GetPaletteColor( aColor );
     486             : 
     487           0 :                                     aSumRed   += aColor.GetRed();
     488           0 :                                     aSumGreen += aColor.GetGreen();
     489           0 :                                     aSumBlue  += aColor.GetBlue();
     490             : 
     491           0 :                                     aCount++;
     492             :                                 }
     493             :                             }
     494             : 
     495           0 :                             aResultColor.SetRed(   MinMax( aSumRed   / aCount, 0, 255) );
     496           0 :                             aResultColor.SetGreen( MinMax( aSumGreen / aCount, 0, 255) );
     497           0 :                             aResultColor.SetBlue(  MinMax( aSumBlue  / aCount, 0, 255) );
     498             : 
     499           0 :                             pWriteAccess->SetPixel( y, x, aResultColor );
     500             :                         }
     501             :                     }
     502           0 :                 }
     503             :             }
     504             : 
     505           4 :             aOutBmp.ReleaseAccess( pWriteAccess );
     506           4 :             bRet = true;
     507             :         }
     508             : 
     509           4 :         aBmp.ReleaseAccess( pReadAccess );
     510             :     }
     511             : 
     512             :     // mask processing
     513           4 :     if( bRet && ( rBmpEx.IsTransparent() || ( nRot10 != 0 && nRot10 != 900 && nRot10 != 1800 && nRot10 != 2700 ) ) )
     514             :     {
     515           1 :         bRet = false;
     516             : 
     517           1 :         if( rBmpEx.IsAlpha() )
     518             :         {
     519           0 :             AlphaMask   aAlpha( rBmpEx.GetAlpha() );
     520           0 :             AlphaMask   aOutAlpha;
     521             : 
     522           0 :             pReadAccess = aAlpha.AcquireReadAccess();
     523             : 
     524           0 :             if( pReadAccess )
     525             :             {
     526           0 :                 aOutAlpha = AlphaMask( Size( aTargetWidth, aTargetHeight ) );
     527           0 :                 pWriteAccess = aOutAlpha.AcquireWriteAccess();
     528             : 
     529           0 :                 if( pWriteAccess )
     530             :                 {
     531           0 :                     if( pReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL &&
     532           0 :                         pWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
     533             :                     {
     534           0 :                         if ( !scaleByAveraging )
     535             :                         {
     536             :                             Scanline pLine0, pLine1, pLineW;
     537             : 
     538           0 :                             for( nY = 0; nY < aTargetHeight; nY++ )
     539             :                             {
     540           0 :                                 nSinY = pSinY[ nY ], nCosY = pCosY[ nY ];
     541           0 :                                 pLineW = pWriteAccess->GetScanline( nY );
     542             : 
     543           0 :                                 for( nX = 0; nX < aTargetWidth; nX++ )
     544             :                                 {
     545           0 :                                     nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
     546           0 :                                     nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
     547             : 
     548           0 :                                     if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) &&
     549             :                                         ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) )
     550             :                                     {
     551           0 :                                         nTmpX = pMapIX[ nUnRotX ], nTmpFX = pMapFX[ nUnRotX ];
     552           0 :                                         nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
     553             : 
     554           0 :                                         pLine0 = pReadAccess->GetScanline( nTmpY++ );
     555           0 :                                         pLine1 = pReadAccess->GetScanline( nTmpY );
     556             : 
     557           0 :                                         const long  nAlpha0 = pLine0[ nTmpX ];
     558           0 :                                         const long  nAlpha2 = pLine1[ nTmpX++ ];
     559           0 :                                         const long  nAlpha1 = pLine0[ nTmpX ];
     560           0 :                                         const long  nAlpha3 = pLine1[ nTmpX ];
     561           0 :                                         const long  n0 = MAP( nAlpha0, nAlpha1, nTmpFX );
     562           0 :                                         const long  n1 = MAP( nAlpha2, nAlpha3, nTmpFX );
     563             : 
     564           0 :                                         *pLineW++ = MAP( n0, n1, nTmpFY );
     565             :                                     }
     566             :                                     else
     567           0 :                                         *pLineW++ = 255;
     568             :                                 }
     569             :                             }
     570             :                         }
     571             :                         else // scaleByAveraging
     572             :                         {
     573           0 :                             const BitmapColor   aTrans( pWriteAccess->GetBestMatchingColor( Color( COL_WHITE ) ) );
     574           0 :                             BitmapColor         aResultColor( 0 );
     575             :                             double aSum, aCount;
     576             : 
     577           0 :                             for( y = 0; y < aTargetHeight; y++ )
     578             :                             {
     579           0 :                                 nSinY = pSinY[ y ];
     580           0 :                                 nCosY = pCosY[ y ];
     581             : 
     582           0 :                                 for( x = 0; x < aTargetWidth; x++ )
     583             :                                 {
     584             : 
     585           0 :                                     double aUnrotatedX = ( pCosX[ x ] - nSinY ) / 256.0;
     586           0 :                                     double aUnrotatedY = ( pSinX[ x ] + nCosY ) / 256.0;
     587             : 
     588           0 :                                     if ( bHMirr )
     589           0 :                                         aUnrotatedX = aUnrotatedWidth - aUnrotatedX - 1;
     590           0 :                                     if ( bVMirr )
     591           0 :                                         aUnrotatedY = aUnrotatedHeight - aUnrotatedY - 1;
     592             : 
     593           0 :                                     if( ( aUnrotatedX >= 0 ) && ( aUnrotatedX < aUnrotatedWidth ) &&
     594             :                                         ( aUnrotatedY >= 0 ) && ( aUnrotatedY < aUnrotatedHeight ) )
     595             :                                     {
     596           0 :                                         double dYStart = ((aUnrotatedY + 0.5) * fRevScaleY) - 0.5;
     597           0 :                                         double dYEnd   = ((aUnrotatedY + 1.5) * fRevScaleY) - 0.5;
     598             : 
     599           0 :                                         int yStart = MinMax( dYStart, 0, aBitmapHeight - 1);
     600           0 :                                         int yEnd   = MinMax( dYEnd,   0, aBitmapHeight - 1);
     601             : 
     602           0 :                                         double dXStart = ((aUnrotatedX + 0.5) * fRevScaleX) - 0.5;
     603           0 :                                         double dXEnd   = ((aUnrotatedX + 1.5) * fRevScaleX) - 0.5;
     604             : 
     605           0 :                                         int xStart = MinMax( dXStart, 0, aBitmapWidth - 1);
     606           0 :                                         int xEnd   = MinMax( dXEnd,   0, aBitmapWidth - 1);
     607             : 
     608           0 :                                         aSum = 0.0;
     609           0 :                                         aCount = 0;
     610             : 
     611           0 :                                         for (int yIn = yStart; yIn <= yEnd; yIn++)
     612             :                                         {
     613           0 :                                             for (int xIn = xStart; xIn <= xEnd; xIn++)
     614             :                                             {
     615           0 :                                                 aSum += pReadAccess->GetPixel( yIn, xIn ).GetIndex();
     616           0 :                                                 aCount++;
     617             :                                             }
     618             :                                         }
     619           0 :                                         aResultColor.SetIndex( MinMax( aSum  / aCount, 0, 255) );
     620           0 :                                         pWriteAccess->SetPixel( y, x, aResultColor );
     621             :                                     }
     622             :                                     else
     623             :                                     {
     624           0 :                                         pWriteAccess->SetPixel( y, x, aTrans );
     625             :                                     }
     626             :                                 }
     627           0 :                             }
     628             :                         }
     629             :                     }
     630             :                     else
     631             :                     {
     632           0 :                         const BitmapColor   aTrans( pWriteAccess->GetBestMatchingColor( Color( COL_WHITE ) ) );
     633           0 :                         BitmapColor         aAlphaVal( 0 );
     634             : 
     635           0 :                         for( nY = 0; nY < aTargetHeight; nY++ )
     636             :                         {
     637           0 :                             nSinY = pSinY[ nY ], nCosY = pCosY[ nY ];
     638             : 
     639           0 :                             for( nX = 0; nX < aTargetWidth; nX++ )
     640             :                             {
     641           0 :                                 nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
     642           0 :                                 nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
     643             : 
     644           0 :                                 if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) &&
     645             :                                     ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) )
     646             :                                 {
     647           0 :                                     nTmpX = pMapIX[ nUnRotX ]; nTmpFX = pMapFX[ nUnRotX ];
     648           0 :                                     nTmpY = pMapIY[ nUnRotY ], nTmpFY = pMapFY[ nUnRotY ];
     649             : 
     650           0 :                                     const long  nAlpha0 = pReadAccess->GetPixel( nTmpY, nTmpX ).GetIndex();
     651           0 :                                     const long  nAlpha1 = pReadAccess->GetPixel( nTmpY, ++nTmpX ).GetIndex();
     652           0 :                                     const long  nAlpha3 = pReadAccess->GetPixel( ++nTmpY, nTmpX ).GetIndex();
     653           0 :                                     const long  nAlpha2 = pReadAccess->GetPixel( nTmpY, --nTmpX ).GetIndex();
     654           0 :                                     const long  n0 = MAP( nAlpha0, nAlpha1, nTmpFX );
     655           0 :                                     const long  n1 = MAP( nAlpha2, nAlpha3, nTmpFX );
     656             : 
     657           0 :                                     aAlphaVal.SetIndex( MAP( n0, n1, nTmpFY ) );
     658           0 :                                     pWriteAccess->SetPixel( nY, nX, aAlphaVal );
     659             :                                 }
     660             :                                 else
     661           0 :                                     pWriteAccess->SetPixel( nY, nX, aTrans );
     662             :                             }
     663           0 :                         }
     664             :                     }
     665             : 
     666           0 :                     aOutAlpha.ReleaseAccess( pWriteAccess );
     667           0 :                     bRet = sal_True;
     668             :                 }
     669             : 
     670           0 :                 aAlpha.ReleaseAccess( pReadAccess );
     671             :             }
     672             : 
     673           0 :             if( bRet )
     674           0 :                 rOutBmpEx = BitmapEx( aOutBmp, aOutAlpha );
     675             :         }
     676             :         else
     677             :         {
     678           1 :             Bitmap aOutMsk( Size( aTargetWidth, aTargetHeight ), 1 );
     679           1 :             pWriteAccess = aOutMsk.AcquireWriteAccess();
     680             : 
     681           1 :             if( pWriteAccess )
     682             :             {
     683           1 :                 Bitmap              aMsk( rBmpEx.GetMask() );
     684           1 :                 const BitmapColor   aB( pWriteAccess->GetBestMatchingColor( Color( COL_BLACK ) ) );
     685           1 :                 const BitmapColor   aW( pWriteAccess->GetBestMatchingColor( Color( COL_WHITE ) ) );
     686           1 :                 BitmapReadAccess*   pMAcc = NULL;
     687             : 
     688           1 :                 if( !aMsk || ( ( pMAcc = aMsk.AcquireReadAccess() ) != NULL ) )
     689             :                 {
     690           1 :                     long*       pMapLX = new long[ aUnrotatedWidth ];
     691           1 :                     long*       pMapLY = new long[ aUnrotatedHeight ];
     692           1 :                     BitmapColor aTestB;
     693             : 
     694           1 :                     if( pMAcc )
     695           1 :                         aTestB = pMAcc->GetBestMatchingColor( Color( COL_BLACK ) );
     696             : 
     697             :                     // create new horizontal mapping table
     698         698 :                     for( nX = 0UL; nX < aUnrotatedWidth; nX++ )
     699         697 :                         pMapLX[ nX ] = FRound( (double) pMapIX[ nX ] + pMapFX[ nX ] / 1048576. );
     700             : 
     701             :                     // create new vertical mapping table
     702          96 :                     for( nY = 0UL; nY < aUnrotatedHeight; nY++ )
     703          95 :                         pMapLY[ nY ] = FRound( (double) pMapIY[ nY ] + pMapFY[ nY ] / 1048576. );
     704             : 
     705             :                     // do mask rotation
     706          96 :                     for( nY = 0; nY < aTargetHeight; nY++ )
     707             :                     {
     708          95 :                         nSinY = pSinY[ nY ];
     709          95 :                         nCosY = pCosY[ nY ];
     710             : 
     711       66310 :                         for( nX = 0; nX < aTargetWidth; nX++ )
     712             :                         {
     713       66215 :                             nUnRotX = ( pCosX[ nX ] - nSinY ) >> 8;
     714       66215 :                             nUnRotY = ( pSinX[ nX ] + nCosY ) >> 8;
     715             : 
     716       66215 :                             if( ( nUnRotX >= 0L ) && ( nUnRotX < aUnrotatedWidth ) &&
     717             :                                 ( nUnRotY >= 0L ) && ( nUnRotY < aUnrotatedHeight ) )
     718             :                             {
     719      132430 :                                 if( pMAcc )
     720             :                                 {
     721       66215 :                                     if( pMAcc->GetPixel( pMapLY[ nUnRotY ], pMapLX[ nUnRotX ] ) == aTestB )
     722       60639 :                                         pWriteAccess->SetPixel( nY, nX, aB );
     723             :                                     else
     724        5576 :                                         pWriteAccess->SetPixel( nY, nX, aW );
     725             :                                 }
     726             :                                 else
     727           0 :                                     pWriteAccess->SetPixel( nY, nX, aB );
     728             :                             }
     729             :                             else
     730           0 :                                 pWriteAccess->SetPixel( nY, nX, aW );
     731             :                         }
     732             :                     }
     733             : 
     734           1 :                     delete[] pMapLX;
     735           1 :                     delete[] pMapLY;
     736             : 
     737           1 :                     if( pMAcc )
     738           1 :                         aMsk.ReleaseAccess( pMAcc );
     739             : 
     740           1 :                     bRet = sal_True;
     741             :                 }
     742             : 
     743           1 :                 aOutMsk.ReleaseAccess( pWriteAccess );
     744             :             }
     745             : 
     746           1 :             if( bRet )
     747           1 :                 rOutBmpEx = BitmapEx( aOutBmp, aOutMsk );
     748             :         }
     749             : 
     750           1 :         if( !bRet )
     751           0 :             rOutBmpEx = aOutBmp;
     752             :     }
     753             :     else
     754           3 :         rOutBmpEx = aOutBmp;
     755             : 
     756           4 :     delete[] pSinX;
     757           4 :     delete[] pCosX;
     758           4 :     delete[] pSinY;
     759           4 :     delete[] pCosY;
     760             : 
     761           4 :     delete[] pMapIX;
     762           4 :     delete[] pMapFX;
     763           4 :     delete[] pMapIY;
     764           4 :     delete[] pMapFY;
     765             : 
     766           4 :     return bRet;
     767             : }
     768             : 
     769           7 : sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOutputDevice,
     770             :                                        const Point& rPoint, const Size& rSize,
     771             :                                        const BitmapEx& rBitmapEx, const GraphicAttr& rAttributes,
     772             :                                        const sal_uLong /*nFlags*/, BitmapEx* pBmpEx )
     773             : {
     774           7 :     sal_uInt16  nRot10 = rAttributes.GetRotation() % 3600;
     775             : 
     776           7 :     Point   aOutputPointPix;
     777           7 :     Size    aOutputSizePix;
     778           7 :     Point   aUnrotatedPointPix( pOutputDevice->LogicToPixel( rPoint ) );
     779           7 :     Size    aUnrotatedSizePix(  pOutputDevice->LogicToPixel( rSize ) );
     780             : 
     781           7 :     bool    bRet = false;
     782             : 
     783           7 :     if( nRot10 )
     784             :     {
     785           0 :         Polygon aPoly( Rectangle( rPoint, rSize ) );
     786           0 :         aPoly.Rotate( rPoint, nRot10 );
     787           0 :         const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
     788           0 :         aOutputPointPix = pOutputDevice->LogicToPixel( aRotBoundRect.TopLeft() );
     789           0 :         aOutputSizePix  = pOutputDevice->LogicToPixel( aRotBoundRect.GetSize() );
     790             :     }
     791             :     else
     792             :     {
     793           7 :         aOutputPointPix = aUnrotatedPointPix;
     794           7 :         aOutputSizePix  = aUnrotatedSizePix;
     795             :     }
     796             : 
     797           7 :     if( aUnrotatedSizePix.Width() && aUnrotatedSizePix.Height() )
     798             :     {
     799           7 :         BitmapEx        aBmpEx( rBitmapEx );
     800           7 :         BitmapEx        aOutBmpEx;
     801           7 :         Point           aOutPoint;
     802           7 :         Size            aOutSize;
     803           7 :         const Size&     rBmpSzPix = rBitmapEx.GetSizePixel();
     804           7 :         const long      nW = rBmpSzPix.Width();
     805           7 :         const long      nH = rBmpSzPix.Height();
     806           7 :         long            nStartX = -1, nStartY = -1, nEndX = -1, nEndY = -1;
     807           7 :         bool            bHMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0;
     808           7 :         bool            bVMirr = ( rAttributes.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0;
     809             : 
     810             :         // calculate output sizes
     811           7 :         if( !pBmpEx )
     812             :         {
     813           0 :             Point       aPt;
     814           0 :             Rectangle   aOutRect( aPt, pOutputDevice->GetOutputSizePixel() );
     815           0 :             Rectangle   aBmpRect( aOutputPointPix, aOutputSizePix );
     816             : 
     817           0 :             if( pOutputDevice->GetOutDevType() == OUTDEV_WINDOW )
     818             :             {
     819           0 :                 const Region aPaintRgn( ( (Window*) pOutputDevice )->GetPaintRegion() );
     820           0 :                 if( !aPaintRgn.IsNull() )
     821           0 :                     aOutRect.Intersection( pOutputDevice->LogicToPixel( aPaintRgn.GetBoundRect() ) );
     822             :             }
     823             : 
     824           0 :             aOutRect.Intersection( aBmpRect );
     825             : 
     826           0 :             if( !aOutRect.IsEmpty() )
     827             :             {
     828           0 :                 aOutPoint = pOutputDevice->PixelToLogic( aOutRect.TopLeft() );
     829           0 :                 aOutSize = pOutputDevice->PixelToLogic( aOutRect.GetSize() );
     830           0 :                 nStartX = aOutRect.Left() - aBmpRect.Left();
     831           0 :                 nStartY = aOutRect.Top() - aBmpRect.Top();
     832           0 :                 nEndX = aOutRect.Right() - aBmpRect.Left();
     833           0 :                 nEndY = aOutRect.Bottom() - aBmpRect.Top();
     834             :             }
     835             :             else
     836             :             {
     837           0 :                 nStartX = -1L; // invalid
     838             :             }
     839             :         }
     840             :         else
     841             :         {
     842           7 :             aOutPoint = pOutputDevice->PixelToLogic( aOutputPointPix );
     843           7 :             aOutSize = pOutputDevice->PixelToLogic( aOutputSizePix );
     844           7 :             nStartX = nStartY = 0;
     845           7 :             nEndX = aOutputSizePix.Width() - 1L;
     846           7 :             nEndY = aOutputSizePix.Height() - 1L;
     847             :         }
     848             : 
     849             :         // do transformation
     850           7 :         if( nStartX >= 0L )
     851             :         {
     852           7 :             const bool bSimple = ( 1 == nW || 1 == nH );
     853             : 
     854           7 :             if( nRot10 )
     855             :             {
     856           0 :                 if( bSimple )
     857             :                 {
     858           0 :                     bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSizePix );
     859             : 
     860           0 :                     if( bRet )
     861           0 :                         aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
     862             :                 }
     863             :                 else
     864             :                 {
     865             :                     bRet = ImplCreateRotatedScaled( aBmpEx, rAttributes,
     866             :                                                     nRot10, aUnrotatedSizePix,
     867             :                                                     nStartX, nEndX, nStartY, nEndY,
     868           0 :                                                     aOutBmpEx );
     869             :                 }
     870             :             }
     871             :             else
     872             :             {
     873           7 :                 if( !bHMirr && !bVMirr && aOutputSizePix == rBmpSzPix )
     874             :                 {
     875           3 :                     aOutPoint = pOutputDevice->PixelToLogic( aOutputPointPix );
     876           3 :                     aOutSize  = pOutputDevice->PixelToLogic( aOutputSizePix );
     877           3 :                     aOutBmpEx = aBmpEx;
     878           3 :                     bRet      = true;
     879             :                 }
     880             :                 else
     881             :                 {
     882           4 :                     if( bSimple )
     883             :                     {
     884           0 :                         bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) );
     885             :                     }
     886             :                     else
     887             :                     {
     888             :                         bRet = ImplCreateRotatedScaled( aBmpEx, rAttributes,
     889             :                                                     nRot10, aUnrotatedSizePix,
     890             :                                                     nStartX, nEndX, nStartY, nEndY,
     891           4 :                                                     aOutBmpEx );
     892             :                     }
     893             :                 }
     894             :             }
     895             : 
     896           7 :             if( bRet )
     897             :             {
     898             :                 // Attribute adjustment if neccessary
     899           7 :                 if( rAttributes.IsSpecialDrawMode() || rAttributes.IsAdjusted() || rAttributes.IsTransparent() )
     900           0 :                     ImplAdjust( aOutBmpEx, rAttributes, ADJUSTMENT_DRAWMODE | ADJUSTMENT_COLORS | ADJUSTMENT_TRANSPARENCY );
     901             : 
     902             :                 // OutDev adjustment if neccessary
     903           7 :                 if( pOutputDevice->GetOutDevType() != OUTDEV_PRINTER && pOutputDevice->GetBitCount() <= 8 && aOutBmpEx.GetBitCount() >= 8 )
     904           0 :                     aOutBmpEx.Dither( BMP_DITHER_MATRIX );
     905             :             }
     906             :         }
     907             : 
     908             :         // Create output
     909           7 :         if( bRet )
     910             :         {
     911           7 :             if( !pBmpEx )
     912           0 :                 pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, aOutBmpEx );
     913             :             else
     914             :             {
     915           7 :                 if( !rAttributes.IsTransparent() && !aOutBmpEx.IsAlpha() )
     916           6 :                     aOutBmpEx = BitmapEx( aOutBmpEx.GetBitmap().CreateDisplayBitmap( pOutputDevice ), aOutBmpEx.GetMask() );
     917             : 
     918           7 :                 pOutputDevice->DrawBitmapEx( aOutPoint, aOutSize, *pBmpEx = aOutBmpEx );
     919             :             }
     920           7 :         }
     921             :     }
     922             : 
     923           7 :     return bRet;
     924             : }
     925             : 
     926             : // This function checks whether the bitmap is usable for skipping
     927             : // mtf rendering by using just this one bitmap (i.e. in case the metafile
     928             : // contains just this one pixmap that covers the entire metafile area).
     929           0 : static BitmapEx checkMetadataBitmap( const BitmapEx& rBmpEx,
     930             :                                      Point    rSrcPoint,
     931             :                                      Size     rSrcSize,
     932             :                                      const Point&    rDestPoint,
     933             :                                      const Size&     rDestSize,
     934             :                                      const Size&     rRefSize,
     935             :                                      bool&           o_rbNonBitmapActionEncountered )
     936             : {
     937             : // NOTE: If you do changes in this function, change checkMetadataBitmap() in grfcache.cxx too.
     938           0 :     BitmapEx aBmpEx;
     939           0 :     if( rSrcSize == Size())
     940           0 :         rSrcSize = rBmpEx.GetSizePixel();
     941             : 
     942           0 :     if( rDestPoint != Point( 0, 0 ))
     943             :     {   // The pixmap in the metafile has an offset (and so would not cover)
     944             :         // the entire result -> fall back to mtf rendering.
     945           0 :         o_rbNonBitmapActionEncountered = true;
     946           0 :         return aBmpEx;
     947             :     }
     948           0 :     if( rDestSize != rRefSize )
     949             :     {   // The pixmap is not fullscale (does not cover the entire metafile area).
     950             :         // HACK: The code here should refuse to use the bitmap directly
     951             :         // and fall back to mtf rendering, but there seem to be metafiles
     952             :         // that do not specify exactly their area (the Windows API requires apps
     953             :         // the specify it manually, the rectangle is specified as topleft/bottomright
     954             :         // rather than topleft/size [which may be confusing], and the docs
     955             :         // on the exact meaning are somewhat confusing as well), so if it turns
     956             :         // out this metafile really contains just one bitmap and no other painting,
     957             :         // and if the sizes almost match, just use the pixmap (which will be scaled
     958             :         // to fit exactly the requested size, so there should not be any actual problem
     959             :         // caused by this small difference). This will allow caching of the resulting
     960             :         // (scaled) pixmap, which can make a noticeable performance difference.
     961           0 :         if( rBmpEx.GetSizePixel().Width() > 100 && rBmpEx.GetSizePixel().Height() > 100
     962           0 :             && abs( rDestSize.Width() - rRefSize.Width()) < 5
     963           0 :             && abs( rDestSize.Height() - rRefSize.Height()) < 5 )
     964             :             ; // ok, assume it's close enough
     965             :         else
     966             :         {  // fall back to mtf rendering
     967           0 :             o_rbNonBitmapActionEncountered = true;
     968           0 :             return aBmpEx;
     969             :         }
     970             :     }
     971             : 
     972           0 :     aBmpEx = rBmpEx;
     973             : 
     974           0 :     if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) ||
     975           0 :         rSrcSize != rBmpEx.GetSizePixel() )
     976             :     {
     977             :         // crop bitmap to given source rectangle (no
     978             :         // need to copy and convert the whole bitmap)
     979             :         const Rectangle aCropRect( rSrcPoint,
     980           0 :                                    rSrcSize );
     981           0 :         aBmpEx.Crop( aCropRect );
     982             :     }
     983             : 
     984           0 :     return aBmpEx;
     985             : }
     986             : 
     987           1 : sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
     988             :                                        const Point& rPt, const Size& rSz,
     989             :                                        const GDIMetaFile& rMtf, const GraphicAttr& rAttr,
     990             :                                        const sal_uLong /*nFlags*/, GDIMetaFile& rOutMtf, BitmapEx& rOutBmpEx )
     991             : {
     992           1 :     const Size aNewSize( rMtf.GetPrefSize() );
     993             : 
     994           1 :     rOutMtf = rMtf;
     995             : 
     996             :     // Count bitmap actions, and flag actions that paint, but
     997             :     // are no bitmaps.
     998           1 :     sal_Int32   nNumBitmaps(0);
     999           1 :     bool        bNonBitmapActionEncountered(false);
    1000           1 :     if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() )
    1001             :     {
    1002           1 :         const double fGrfWH = (double) aNewSize.Width() / aNewSize.Height();
    1003           1 :         const double fOutWH = (double) rSz.Width() / rSz.Height();
    1004             : 
    1005           1 :         const double fScaleX = fOutWH / fGrfWH;
    1006           1 :         const double fScaleY = 1.0;
    1007             : 
    1008           1 :         const MapMode rPrefMapMode( rMtf.GetPrefMapMode() );
    1009           1 :         const Size rSizePix( pOut->LogicToPixel( aNewSize, rPrefMapMode ) );
    1010             : 
    1011             : // NOTE: If you do changes in this function, check GraphicDisplayCacheEntry::IsCacheableAsBitmap
    1012             : // in grfcache.cxx too.
    1013             : 
    1014             :         // Determine whether the metafile basically displays
    1015             :         // a single bitmap (in which case that bitmap is simply used directly
    1016             :         // instead of playing the metafile). Note that
    1017             :         // the solution, as implemented here, is quite suboptimal (the
    1018             :         // cases where a mtf consisting basically of a single bitmap,
    1019             :         // that fail to pass the test below, are probably frequent). A
    1020             :         // better solution would involve FSAA, but that's currently
    1021             :         // expensive, and might trigger bugs on display drivers, if
    1022             :         // VDevs get bigger than the actual screen.
    1023             :         sal_uInt32  nCurPos;
    1024             :         MetaAction* pAct;
    1025          35 :         for( nCurPos = 0, pAct = (MetaAction*)rOutMtf.FirstAction(); pAct;
    1026             :              pAct = (MetaAction*)rOutMtf.NextAction(), nCurPos++ )
    1027             :         {
    1028          34 :             MetaAction* pModAct = NULL;
    1029          34 :             switch( pAct->GetType() )
    1030             :             {
    1031             :                 case META_FONT_ACTION:
    1032             :                 {
    1033             :                     // taking care of font width default if scaling metafile.
    1034           1 :                     MetaFontAction* pA = (MetaFontAction*)pAct;
    1035           1 :                     Font aFont( pA->GetFont() );
    1036           1 :                     if ( !aFont.GetWidth() )
    1037             :                     {
    1038           0 :                         FontMetric aFontMetric( pOut->GetFontMetric( aFont ) );
    1039           0 :                         aFont.SetWidth( aFontMetric.GetWidth() );
    1040           0 :                         pModAct = new MetaFontAction( aFont );
    1041           1 :                     }
    1042             :                 }
    1043             :                     // FALLTHROUGH intended
    1044             :                 case META_NULL_ACTION:
    1045             :                     // FALLTHROUGH intended
    1046             : 
    1047             :                     // OutDev state changes (which don't affect bitmap
    1048             :                     // output)
    1049             :                 case META_LINECOLOR_ACTION:
    1050             :                     // FALLTHROUGH intended
    1051             :                 case META_FILLCOLOR_ACTION:
    1052             :                     // FALLTHROUGH intended
    1053             :                 case META_TEXTCOLOR_ACTION:
    1054             :                     // FALLTHROUGH intended
    1055             :                 case META_TEXTFILLCOLOR_ACTION:
    1056             :                     // FALLTHROUGH intended
    1057             :                 case META_TEXTALIGN_ACTION:
    1058             :                     // FALLTHROUGH intended
    1059             :                 case META_TEXTLINECOLOR_ACTION:
    1060             :                     // FALLTHROUGH intended
    1061             :                 case META_TEXTLINE_ACTION:
    1062             :                     // FALLTHROUGH intended
    1063             :                 case META_PUSH_ACTION:
    1064             :                     // FALLTHROUGH intended
    1065             :                 case META_POP_ACTION:
    1066             :                     // FALLTHROUGH intended
    1067             :                 case META_LAYOUTMODE_ACTION:
    1068             :                     // FALLTHROUGH intended
    1069             :                 case META_TEXTLANGUAGE_ACTION:
    1070             :                     // FALLTHROUGH intended
    1071             :                 case META_COMMENT_ACTION:
    1072          30 :                     break;
    1073             : 
    1074             :                     // bitmap output methods
    1075             :                 case META_BMP_ACTION:
    1076           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
    1077             :                     {
    1078           0 :                         MetaBmpAction* pAction = (MetaBmpAction*)pAct;
    1079             : 
    1080             :                         rOutBmpEx = checkMetadataBitmap(
    1081           0 :                             BitmapEx( pAction->GetBitmap()),
    1082             :                             Point(), Size(),
    1083           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
    1084             :                                                 rPrefMapMode ),
    1085           0 :                             pAction->GetBitmap().GetSizePixel(),
    1086             :                             rSizePix,
    1087           0 :                             bNonBitmapActionEncountered );
    1088             :                     }
    1089           0 :                     ++nNumBitmaps;
    1090           0 :                     break;
    1091             : 
    1092             :                 case META_BMPSCALE_ACTION:
    1093           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
    1094             :                     {
    1095           0 :                         MetaBmpScaleAction* pAction = (MetaBmpScaleAction*)pAct;
    1096             : 
    1097             :                         rOutBmpEx = checkMetadataBitmap(
    1098           0 :                             BitmapEx( pAction->GetBitmap()),
    1099             :                             Point(), Size(),
    1100           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
    1101             :                                                 rPrefMapMode ),
    1102           0 :                             pOut->LogicToPixel( pAction->GetSize(),
    1103             :                                                 rPrefMapMode ),
    1104             :                             rSizePix,
    1105           0 :                             bNonBitmapActionEncountered );
    1106             :                     }
    1107           0 :                     ++nNumBitmaps;
    1108           0 :                     break;
    1109             : 
    1110             :                 case META_BMPSCALEPART_ACTION:
    1111           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
    1112             :                     {
    1113           0 :                         MetaBmpScalePartAction* pAction = (MetaBmpScalePartAction*)pAct;
    1114             : 
    1115             :                         rOutBmpEx = checkMetadataBitmap(
    1116           0 :                                                     BitmapEx( pAction->GetBitmap() ),
    1117           0 :                                                     pAction->GetSrcPoint(),
    1118           0 :                                                     pAction->GetSrcSize(),
    1119           0 :                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
    1120             :                                                                         rPrefMapMode ),
    1121           0 :                                                     pOut->LogicToPixel( pAction->GetDestSize(),
    1122             :                                                                         rPrefMapMode ),
    1123             :                                                     rSizePix,
    1124           0 :                                                     bNonBitmapActionEncountered );
    1125             :                     }
    1126           0 :                     ++nNumBitmaps;
    1127           0 :                     break;
    1128             : 
    1129             :                 case META_BMPEX_ACTION:
    1130           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
    1131             :                     {
    1132           0 :                         MetaBmpExAction* pAction = (MetaBmpExAction*)pAct;
    1133             : 
    1134             :                         rOutBmpEx = checkMetadataBitmap(
    1135           0 :                             pAction->GetBitmapEx(),
    1136             :                             Point(), Size(),
    1137           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
    1138             :                                                 rPrefMapMode ),
    1139           0 :                             pAction->GetBitmapEx().GetSizePixel(),
    1140             :                             rSizePix,
    1141           0 :                             bNonBitmapActionEncountered );
    1142             :                     }
    1143           0 :                     ++nNumBitmaps;
    1144           0 :                     break;
    1145             : 
    1146             :                 case META_BMPEXSCALE_ACTION:
    1147           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
    1148             :                     {
    1149           0 :                         MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*)pAct;
    1150             : 
    1151             :                         rOutBmpEx = checkMetadataBitmap(
    1152           0 :                             pAction->GetBitmapEx(),
    1153             :                             Point(), Size(),
    1154           0 :                             pOut->LogicToPixel( pAction->GetPoint(),
    1155             :                                                 rPrefMapMode ),
    1156           0 :                             pOut->LogicToPixel( pAction->GetSize(),
    1157             :                                                 rPrefMapMode ),
    1158             :                             rSizePix,
    1159           0 :                             bNonBitmapActionEncountered );
    1160             :                     }
    1161           0 :                     ++nNumBitmaps;
    1162           0 :                     break;
    1163             : 
    1164             :                 case META_BMPEXSCALEPART_ACTION:
    1165           0 :                     if( !nNumBitmaps && !bNonBitmapActionEncountered )
    1166             :                     {
    1167           0 :                         MetaBmpExScalePartAction* pAction = (MetaBmpExScalePartAction*)pAct;
    1168             : 
    1169           0 :                         rOutBmpEx = checkMetadataBitmap( pAction->GetBitmapEx(),
    1170           0 :                                                     pAction->GetSrcPoint(),
    1171           0 :                                                     pAction->GetSrcSize(),
    1172           0 :                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
    1173             :                                                                         rPrefMapMode ),
    1174           0 :                                                     pOut->LogicToPixel( pAction->GetDestSize(),
    1175             :                                                                         rPrefMapMode ),
    1176             :                                                     rSizePix,
    1177           0 :                                                     bNonBitmapActionEncountered );
    1178             :                     }
    1179           0 :                     ++nNumBitmaps;
    1180           0 :                     break;
    1181             : 
    1182             :                     // these actions actually output something (that's
    1183             :                     // different from a bitmap)
    1184             :                 case META_RASTEROP_ACTION:
    1185           1 :                     if( ((MetaRasterOpAction*)pAct)->GetRasterOp() == ROP_OVERPAINT )
    1186           1 :                         break;
    1187             :                     // FALLTHROUGH intended
    1188             :                 case META_PIXEL_ACTION:
    1189             :                     // FALLTHROUGH intended
    1190             :                 case META_POINT_ACTION:
    1191             :                     // FALLTHROUGH intended
    1192             :                 case META_LINE_ACTION:
    1193             :                     // FALLTHROUGH intended
    1194             :                 case META_RECT_ACTION:
    1195             :                     // FALLTHROUGH intended
    1196             :                 case META_ROUNDRECT_ACTION:
    1197             :                     // FALLTHROUGH intended
    1198             :                 case META_ELLIPSE_ACTION:
    1199             :                     // FALLTHROUGH intended
    1200             :                 case META_ARC_ACTION:
    1201             :                     // FALLTHROUGH intended
    1202             :                 case META_PIE_ACTION:
    1203             :                     // FALLTHROUGH intended
    1204             :                 case META_CHORD_ACTION:
    1205             :                     // FALLTHROUGH intended
    1206             :                 case META_POLYLINE_ACTION:
    1207             :                     // FALLTHROUGH intended
    1208             :                 case META_POLYGON_ACTION:
    1209             :                     // FALLTHROUGH intended
    1210             :                 case META_POLYPOLYGON_ACTION:
    1211             :                     // FALLTHROUGH intended
    1212             : 
    1213             :                 case META_TEXT_ACTION:
    1214             :                     // FALLTHROUGH intended
    1215             :                 case META_TEXTARRAY_ACTION:
    1216             :                     // FALLTHROUGH intended
    1217             :                 case META_STRETCHTEXT_ACTION:
    1218             :                     // FALLTHROUGH intended
    1219             :                 case META_TEXTRECT_ACTION:
    1220             :                     // FALLTHROUGH intended
    1221             : 
    1222             :                 case META_MASK_ACTION:
    1223             :                     // FALLTHROUGH intended
    1224             :                 case META_MASKSCALE_ACTION:
    1225             :                     // FALLTHROUGH intended
    1226             :                 case META_MASKSCALEPART_ACTION:
    1227             :                     // FALLTHROUGH intended
    1228             : 
    1229             :                 case META_GRADIENT_ACTION:
    1230             :                     // FALLTHROUGH intended
    1231             :                 case META_HATCH_ACTION:
    1232             :                     // FALLTHROUGH intended
    1233             :                 case META_WALLPAPER_ACTION:
    1234             :                     // FALLTHROUGH intended
    1235             : 
    1236             :                 case META_TRANSPARENT_ACTION:
    1237             :                     // FALLTHROUGH intended
    1238             :                 case META_EPS_ACTION:
    1239             :                     // FALLTHROUGH intended
    1240             :                 case META_FLOATTRANSPARENT_ACTION:
    1241             :                     // FALLTHROUGH intended
    1242             :                 case META_GRADIENTEX_ACTION:
    1243             :                     // FALLTHROUGH intended
    1244             : 
    1245             :                     // OutDev state changes that _do_ affect bitmap
    1246             :                     // output
    1247             :                 case META_CLIPREGION_ACTION:
    1248             :                     // FALLTHROUGH intended
    1249             :                 case META_ISECTRECTCLIPREGION_ACTION:
    1250             :                     // FALLTHROUGH intended
    1251             :                 case META_ISECTREGIONCLIPREGION_ACTION:
    1252             :                     // FALLTHROUGH intended
    1253             :                 case META_MOVECLIPREGION_ACTION:
    1254             :                     // FALLTHROUGH intended
    1255             : 
    1256             :                 case META_MAPMODE_ACTION:
    1257             :                     // FALLTHROUGH intended
    1258             :                 case META_REFPOINT_ACTION:
    1259             :                     // FALLTHROUGH intended
    1260             :                 default:
    1261           3 :                     bNonBitmapActionEncountered = true;
    1262           3 :                     break;
    1263             :             }
    1264          34 :             if ( pModAct )
    1265             :             {
    1266           0 :                 rOutMtf.ReplaceAction( pModAct, nCurPos );
    1267           0 :                 pAct->Delete();
    1268             :             }
    1269             :             else
    1270             :             {
    1271          34 :                 if( pAct->GetRefCount() > 1 )
    1272             :                 {
    1273          34 :                     rOutMtf.ReplaceAction( pModAct = pAct->Clone(), nCurPos );
    1274          34 :                     pAct->Delete();
    1275             :                 }
    1276             :                 else
    1277           0 :                     pModAct = pAct;
    1278             :             }
    1279          34 :             pModAct->Scale( fScaleX, fScaleY );
    1280             :         }
    1281           1 :         rOutMtf.SetPrefSize( Size( FRound( aNewSize.Width() * fScaleX ),
    1282           2 :                                    FRound( aNewSize.Height() * fScaleY ) ) );
    1283             :     }
    1284             : 
    1285           1 :     if( nNumBitmaps != 1 || bNonBitmapActionEncountered )
    1286             :     {
    1287           1 :         if( rAttr.IsSpecialDrawMode() || rAttr.IsAdjusted() || rAttr.IsMirrored() || rAttr.IsRotated() || rAttr.IsTransparent() )
    1288           0 :             ImplAdjust( rOutMtf, rAttr, ADJUSTMENT_ALL );
    1289             : 
    1290           1 :         ImplDraw( pOut, rPt, rSz, rOutMtf, rAttr );
    1291           1 :         rOutBmpEx = BitmapEx();
    1292             :     }
    1293             : 
    1294           1 :     return sal_True;
    1295             : }
    1296             : 
    1297           1 : void GraphicManager::ImplAdjust( BitmapEx& rBmpEx, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags )
    1298             : {
    1299           1 :     GraphicAttr aAttr( rAttr );
    1300             : 
    1301           1 :     if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() )
    1302             :     {
    1303           0 :         switch( aAttr.GetDrawMode() )
    1304             :         {
    1305             :             case( GRAPHICDRAWMODE_MONO ):
    1306           0 :                 rBmpEx.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
    1307           0 :             break;
    1308             : 
    1309             :             case( GRAPHICDRAWMODE_GREYS ):
    1310           0 :                 rBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
    1311           0 :             break;
    1312             : 
    1313             :             case( GRAPHICDRAWMODE_WATERMARK ):
    1314             :             {
    1315           0 :                 aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET );
    1316           0 :                 aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET );
    1317             :             }
    1318           0 :             break;
    1319             : 
    1320             :             default:
    1321           0 :             break;
    1322             :         }
    1323             :     }
    1324             : 
    1325           1 :     if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() )
    1326             :     {
    1327           0 :         rBmpEx.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(),
    1328           0 :                        aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(),
    1329           0 :                        aAttr.GetGamma(), aAttr.IsInvert() );
    1330             :     }
    1331             : 
    1332           1 :     if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() )
    1333             :     {
    1334           1 :         rBmpEx.Mirror( aAttr.GetMirrorFlags() );
    1335             :     }
    1336             : 
    1337           1 :     if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() )
    1338             :     {
    1339           0 :         rBmpEx.Rotate( aAttr.GetRotation(), Color( COL_TRANSPARENT ) );
    1340             :     }
    1341             : 
    1342           1 :     if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() )
    1343             :     {
    1344           0 :         AlphaMask   aAlpha;
    1345           0 :         sal_uInt8       cTrans = aAttr.GetTransparency();
    1346             : 
    1347           0 :         if( !rBmpEx.IsTransparent() )
    1348           0 :             aAlpha = AlphaMask( rBmpEx.GetSizePixel(), &cTrans );
    1349           0 :         else if( !rBmpEx.IsAlpha() )
    1350             :         {
    1351           0 :             aAlpha = rBmpEx.GetMask();
    1352           0 :             aAlpha.Replace( 0, cTrans );
    1353             :         }
    1354             :         else
    1355             :         {
    1356           0 :             aAlpha = rBmpEx.GetAlpha();
    1357           0 :             BitmapWriteAccess* pA = aAlpha.AcquireWriteAccess();
    1358             : 
    1359           0 :             if( pA )
    1360             :             {
    1361           0 :                 sal_uLong       nTrans = cTrans, nNewTrans;
    1362           0 :                 const long  nWidth = pA->Width(), nHeight = pA->Height();
    1363             : 
    1364           0 :                 if( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
    1365             :                 {
    1366           0 :                     for( long nY = 0; nY < nHeight; nY++ )
    1367             :                     {
    1368           0 :                         Scanline pAScan = pA->GetScanline( nY );
    1369             : 
    1370           0 :                         for( long nX = 0; nX < nWidth; nX++ )
    1371             :                         {
    1372           0 :                             nNewTrans = nTrans + *pAScan;
    1373           0 :                             *pAScan++ = (sal_uInt8) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans );
    1374             :                         }
    1375             :                     }
    1376             :                 }
    1377             :                 else
    1378             :                 {
    1379           0 :                     BitmapColor aAlphaValue( 0 );
    1380             : 
    1381           0 :                     for( long nY = 0; nY < nHeight; nY++ )
    1382             :                     {
    1383           0 :                         for( long nX = 0; nX < nWidth; nX++ )
    1384             :                         {
    1385           0 :                             nNewTrans = nTrans + pA->GetPixel( nY, nX ).GetIndex();
    1386           0 :                             aAlphaValue.SetIndex( (sal_uInt8) ( ( nNewTrans & 0xffffff00 ) ? 255 : nNewTrans ) );
    1387           0 :                             pA->SetPixel( nY, nX, aAlphaValue );
    1388             :                         }
    1389           0 :                     }
    1390             :                 }
    1391             : 
    1392           0 :                 aAlpha.ReleaseAccess( pA );
    1393             :             }
    1394             :         }
    1395             : 
    1396           0 :         rBmpEx = BitmapEx( rBmpEx.GetBitmap(), aAlpha );
    1397           1 :     }
    1398           1 : }
    1399             : 
    1400           0 : void GraphicManager::ImplAdjust( GDIMetaFile& rMtf, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags )
    1401             : {
    1402           0 :     GraphicAttr aAttr( rAttr );
    1403             : 
    1404           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() )
    1405             :     {
    1406           0 :         switch( aAttr.GetDrawMode() )
    1407             :         {
    1408             :             case( GRAPHICDRAWMODE_MONO ):
    1409           0 :                 rMtf.Convert( MTF_CONVERSION_1BIT_THRESHOLD );
    1410           0 :             break;
    1411             : 
    1412             :             case( GRAPHICDRAWMODE_GREYS ):
    1413           0 :                 rMtf.Convert( MTF_CONVERSION_8BIT_GREYS );
    1414           0 :             break;
    1415             : 
    1416             :             case( GRAPHICDRAWMODE_WATERMARK ):
    1417             :             {
    1418           0 :                 aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET );
    1419           0 :                 aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET );
    1420             :             }
    1421           0 :             break;
    1422             : 
    1423             :             default:
    1424           0 :             break;
    1425             :         }
    1426             :     }
    1427             : 
    1428           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() )
    1429             :     {
    1430           0 :         rMtf.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(),
    1431           0 :                      aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(),
    1432           0 :                      aAttr.GetGamma(), aAttr.IsInvert() );
    1433             :     }
    1434             : 
    1435           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() )
    1436             :     {
    1437           0 :         rMtf.Mirror( aAttr.GetMirrorFlags() );
    1438             :     }
    1439             : 
    1440           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() )
    1441             :     {
    1442           0 :         rMtf.Rotate( aAttr.GetRotation() );
    1443             :     }
    1444             : 
    1445           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() )
    1446             :     {
    1447             :         OSL_FAIL( "Missing implementation: Mtf-Transparency" );
    1448           0 :     }
    1449           0 : }
    1450             : 
    1451           0 : void GraphicManager::ImplAdjust( Animation& rAnimation, const GraphicAttr& rAttr, sal_uLong nAdjustmentFlags )
    1452             : {
    1453           0 :     GraphicAttr aAttr( rAttr );
    1454             : 
    1455           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_DRAWMODE ) && aAttr.IsSpecialDrawMode() )
    1456             :     {
    1457           0 :         switch( aAttr.GetDrawMode() )
    1458             :         {
    1459             :             case( GRAPHICDRAWMODE_MONO ):
    1460           0 :                 rAnimation.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
    1461           0 :             break;
    1462             : 
    1463             :             case( GRAPHICDRAWMODE_GREYS ):
    1464           0 :                 rAnimation.Convert( BMP_CONVERSION_8BIT_GREYS );
    1465           0 :             break;
    1466             : 
    1467             :             case( GRAPHICDRAWMODE_WATERMARK ):
    1468             :             {
    1469           0 :                 aAttr.SetLuminance( aAttr.GetLuminance() + WATERMARK_LUM_OFFSET );
    1470           0 :                 aAttr.SetContrast( aAttr.GetContrast() + WATERMARK_CON_OFFSET );
    1471             :             }
    1472           0 :             break;
    1473             : 
    1474             :             default:
    1475           0 :             break;
    1476             :         }
    1477             :     }
    1478             : 
    1479           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_COLORS ) && aAttr.IsAdjusted() )
    1480             :     {
    1481           0 :         rAnimation.Adjust( aAttr.GetLuminance(), aAttr.GetContrast(),
    1482           0 :                            aAttr.GetChannelR(), aAttr.GetChannelG(), aAttr.GetChannelB(),
    1483           0 :                            aAttr.GetGamma(), aAttr.IsInvert() );
    1484             :     }
    1485             : 
    1486           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_MIRROR ) && aAttr.IsMirrored() )
    1487             :     {
    1488           0 :         rAnimation.Mirror( aAttr.GetMirrorFlags() );
    1489             :     }
    1490             : 
    1491           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_ROTATE ) && aAttr.IsRotated() )
    1492             :     {
    1493             :         OSL_FAIL( "Missing implementation: Animation-Rotation" );
    1494             :     }
    1495             : 
    1496           0 :     if( ( nAdjustmentFlags & ADJUSTMENT_TRANSPARENCY ) && aAttr.IsTransparent() )
    1497             :     {
    1498             :         OSL_FAIL( "Missing implementation: Animation-Transparency" );
    1499           0 :     }
    1500           0 : }
    1501             : 
    1502           2 : void GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt, const Size& rSz,
    1503             :                                const GDIMetaFile& rMtf, const GraphicAttr& rAttr )
    1504             : {
    1505           2 :        sal_uInt16   nRot10 = rAttr.GetRotation() % 3600;
    1506           2 :     Point   aOutPt( rPt );
    1507           2 :     Size    aOutSz( rSz );
    1508             : 
    1509           2 :     if( nRot10 )
    1510             :     {
    1511           0 :         Polygon aPoly( Rectangle( aOutPt, aOutSz ) );
    1512             : 
    1513           0 :         aPoly.Rotate( aOutPt, nRot10 );
    1514           0 :         const Rectangle aRotBoundRect( aPoly.GetBoundRect() );
    1515           0 :         aOutPt = aRotBoundRect.TopLeft();
    1516           0 :         aOutSz = aRotBoundRect.GetSize();
    1517             :     }
    1518             : 
    1519           2 :     pOut->Push( PUSH_CLIPREGION );
    1520           2 :     pOut->IntersectClipRegion( Rectangle( aOutPt, aOutSz ) );
    1521             : 
    1522           2 :     ( (GDIMetaFile&) rMtf ).WindStart();
    1523           2 :     ( (GDIMetaFile&) rMtf ).Play( pOut, aOutPt, aOutSz );
    1524           2 :     ( (GDIMetaFile&) rMtf ).WindStart();
    1525             : 
    1526           2 :     pOut->Pop();
    1527           2 : }
    1528             : 
    1529             : struct ImplTileInfo
    1530             : {
    1531           0 :     ImplTileInfo() : aTileTopLeft(), aNextTileTopLeft(), aTileSizePixel(), nTilesEmptyX(0), nTilesEmptyY(0) {}
    1532             : 
    1533             :     Point aTileTopLeft;     // top, left position of the rendered tile
    1534             :     Point aNextTileTopLeft; // top, left position for next recursion
    1535             :                             // level's tile
    1536             :     Size  aTileSizePixel;   // size of the generated tile (might
    1537             :                             // differ from
    1538             :                             // aNextTileTopLeft-aTileTopLeft, because
    1539             :                             // this is nExponent*prevTileSize. The
    1540             :                             // generated tile is always nExponent
    1541             :                             // times the previous tile, such that it
    1542             :                             // can be used in the next stage. The
    1543             :                             // required area coverage is often
    1544             :                             // less. The extraneous area covered is
    1545             :                             // later overwritten by the next stage)
    1546             :     int   nTilesEmptyX;     // number of original tiles empty right of
    1547             :                             // this tile. This counts from
    1548             :                             // aNextTileTopLeft, i.e. the additional
    1549             :                             // area covered by aTileSizePixel is not
    1550             :                             // considered here. This is for
    1551             :                             // unification purposes, as the iterative
    1552             :                             // calculation of the next level's empty
    1553             :                             // tiles has to be based on this value.
    1554             :     int   nTilesEmptyY;     // as above, for Y
    1555             : };
    1556             : 
    1557             : 
    1558           0 : bool GraphicObject::ImplRenderTempTile( VirtualDevice& rVDev, int nExponent,
    1559             :                                         int nNumTilesX, int nNumTilesY,
    1560             :                                         const Size& rTileSizePixel,
    1561             :                                         const GraphicAttr* pAttr, sal_uLong nFlags )
    1562             : {
    1563           0 :     if( nExponent <= 1 )
    1564           0 :         return false;
    1565             : 
    1566             :     // determine MSB factor
    1567           0 :     int nMSBFactor( 1 );
    1568           0 :     while( nNumTilesX / nMSBFactor != 0 ||
    1569             :            nNumTilesY / nMSBFactor != 0 )
    1570             :     {
    1571           0 :         nMSBFactor *= nExponent;
    1572             :     }
    1573             : 
    1574             :     // one less
    1575           0 :     nMSBFactor /= nExponent;
    1576             : 
    1577           0 :     ImplTileInfo aTileInfo;
    1578             : 
    1579             :     // #105229# Switch off mapping (converting to logic and back to
    1580             :     // pixel might cause roundoff errors)
    1581           0 :     sal_Bool bOldMap( rVDev.IsMapModeEnabled() );
    1582           0 :     rVDev.EnableMapMode( sal_False );
    1583             : 
    1584             :     bool bRet( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor, nNumTilesX, nNumTilesY,
    1585           0 :                                         nNumTilesX, nNumTilesY, rTileSizePixel, pAttr, nFlags, aTileInfo ) );
    1586             : 
    1587           0 :     rVDev.EnableMapMode( bOldMap );
    1588             : 
    1589           0 :     return bRet;
    1590             : }
    1591             : 
    1592             : // define for debug drawings
    1593             : //#define DBG_TEST
    1594             : 
    1595             : // see header comment. this works similar to base conversion of a
    1596             : // number, i.e. if the exponent is 10, then the number for every tile
    1597             : // size is given by the decimal place of the corresponding decimal
    1598             : // representation.
    1599           0 : bool GraphicObject::ImplRenderTileRecursive( VirtualDevice& rVDev, int nExponent, int nMSBFactor,
    1600             :                                              int nNumOrigTilesX, int nNumOrigTilesY,
    1601             :                                              int nRemainderTilesX, int nRemainderTilesY,
    1602             :                                              const Size& rTileSizePixel, const GraphicAttr* pAttr,
    1603             :                                              sal_uLong nFlags, ImplTileInfo& rTileInfo )
    1604             : {
    1605             :     // gets loaded with our tile bitmap
    1606           0 :     GraphicObject aTmpGraphic;
    1607             : 
    1608             :     // stores a flag that renders the zero'th tile position
    1609             :     // (i.e. (0,0)+rCurrPos) only if we're at the bottom of the
    1610             :     // recursion stack. All other position already have that tile
    1611             :     // rendered, because the lower levels painted their generated tile
    1612             :     // there.
    1613           0 :     bool bNoFirstTileDraw( false );
    1614             : 
    1615             :     // what's left when we're done with our tile size
    1616           0 :     const int nNewRemainderX( nRemainderTilesX % nMSBFactor );
    1617           0 :     const int nNewRemainderY( nRemainderTilesY % nMSBFactor );
    1618             : 
    1619             :     // gets filled out from the recursive call with info of what's
    1620             :     // been generated
    1621           0 :     ImplTileInfo aTileInfo;
    1622             : 
    1623             :     // current output position while drawing
    1624           0 :     Point aCurrPos;
    1625             :     int nX, nY;
    1626             : 
    1627             :     // check for recursion's end condition: LSB place reached?
    1628           0 :     if( nMSBFactor == 1 )
    1629             :     {
    1630           0 :         aTmpGraphic = *this;
    1631             : 
    1632             :         // set initial tile size -> orig size
    1633           0 :         aTileInfo.aTileSizePixel = rTileSizePixel;
    1634           0 :         aTileInfo.nTilesEmptyX = nNumOrigTilesX;
    1635           0 :         aTileInfo.nTilesEmptyY = nNumOrigTilesY;
    1636             :     }
    1637           0 :     else if( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor/nExponent,
    1638             :                                       nNumOrigTilesX, nNumOrigTilesY,
    1639             :                                       nNewRemainderX, nNewRemainderY,
    1640           0 :                                       rTileSizePixel, pAttr, nFlags, aTileInfo ) )
    1641             :     {
    1642             :         // extract generated tile -> see comment on the first loop below
    1643           0 :         BitmapEx aTileBitmap( rVDev.GetBitmap( aTileInfo.aTileTopLeft, aTileInfo.aTileSizePixel ) );
    1644             : 
    1645           0 :         aTmpGraphic = GraphicObject( aTileBitmap );
    1646             : 
    1647             :         // fill stripes left over from upstream levels:
    1648             :         //
    1649             :         //  x0000
    1650             :         //  0
    1651             :         //  0
    1652             :         //  0
    1653             :         //  0
    1654             :         //
    1655             :         // where x denotes the place filled by our recursive predecessors
    1656             : 
    1657             :         // check whether we have to fill stripes here. Although not
    1658             :         // obvious, there is one case where we can skip this step: if
    1659             :         // the previous recursion level (the one who filled our
    1660             :         // aTileInfo) had zero area to fill, then there are no white
    1661             :         // stripes left, naturally. This happens if the digit
    1662             :         // associated to that level has a zero, and can be checked via
    1663             :         // aTileTopLeft==aNextTileTopLeft.
    1664           0 :         if( aTileInfo.aTileTopLeft != aTileInfo.aNextTileTopLeft )
    1665             :         {
    1666             :             // now fill one row from aTileInfo.aNextTileTopLeft.X() all
    1667             :             // the way to the right
    1668           0 :             aCurrPos.X() = aTileInfo.aNextTileTopLeft.X();
    1669           0 :             aCurrPos.Y() = aTileInfo.aTileTopLeft.Y();
    1670           0 :             for( nX=0; nX < aTileInfo.nTilesEmptyX; nX += nMSBFactor )
    1671             :             {
    1672           0 :                 if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) )
    1673           0 :                     return false;
    1674             : 
    1675           0 :                 aCurrPos.X() += aTileInfo.aTileSizePixel.Width();
    1676             :             }
    1677             : 
    1678             : #ifdef DBG_TEST
    1679             : //          rVDev.SetFillColor( COL_WHITE );
    1680             :             rVDev.SetFillColor();
    1681             :             rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) );
    1682             :             rVDev.DrawEllipse( Rectangle(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y(),
    1683             :                                          aTileInfo.aNextTileTopLeft.X() - 1 + (aTileInfo.nTilesEmptyX/nMSBFactor)*aTileInfo.aTileSizePixel.Width(),
    1684             :                                          aTileInfo.aTileTopLeft.Y() + aTileInfo.aTileSizePixel.Height() - 1) );
    1685             : #endif
    1686             : 
    1687             :             // now fill one column from aTileInfo.aNextTileTopLeft.Y() all
    1688             :             // the way to the bottom
    1689           0 :             aCurrPos.X() = aTileInfo.aTileTopLeft.X();
    1690           0 :             aCurrPos.Y() = aTileInfo.aNextTileTopLeft.Y();
    1691           0 :             for( nY=0; nY < aTileInfo.nTilesEmptyY; nY += nMSBFactor )
    1692             :             {
    1693           0 :                 if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) )
    1694           0 :                     return false;
    1695             : 
    1696           0 :                 aCurrPos.Y() += aTileInfo.aTileSizePixel.Height();
    1697             :             }
    1698             : 
    1699             : #ifdef DBG_TEST
    1700             :             rVDev.DrawEllipse( Rectangle(aTileInfo.aTileTopLeft.X(), aTileInfo.aNextTileTopLeft.Y(),
    1701             :                                          aTileInfo.aTileTopLeft.X() + aTileInfo.aTileSizePixel.Width() - 1,
    1702             :                                          aTileInfo.aNextTileTopLeft.Y() - 1 + (aTileInfo.nTilesEmptyY/nMSBFactor)*aTileInfo.aTileSizePixel.Height()) );
    1703             : #endif
    1704             :         }
    1705             :         else
    1706             :         {
    1707             :             // Thought that aTileInfo.aNextTileTopLeft tile has always
    1708             :             // been drawn already, but that's wrong: typically,
    1709             :             // _parts_ of that tile have been drawn, since the
    1710             :             // previous level generated the tile there. But when
    1711             :             // aTileInfo.aNextTileTopLeft!=aTileInfo.aTileTopLeft, the
    1712             :             // difference between these two values is missing in the
    1713             :             // lower right corner of this first tile. So, can do that
    1714             :             // only here.
    1715           0 :             bNoFirstTileDraw = true;
    1716           0 :         }
    1717             :     }
    1718             :     else
    1719             :     {
    1720           0 :         return false;
    1721             :     }
    1722             : 
    1723             :     // calc number of original tiles in our drawing area without
    1724             :     // remainder
    1725           0 :     nRemainderTilesX -= nNewRemainderX;
    1726           0 :     nRemainderTilesY -= nNewRemainderY;
    1727             : 
    1728             :     // fill tile info for calling method
    1729           0 :     rTileInfo.aTileTopLeft     = aTileInfo.aNextTileTopLeft;
    1730           0 :     rTileInfo.aNextTileTopLeft = Point( rTileInfo.aTileTopLeft.X() + rTileSizePixel.Width()*nRemainderTilesX,
    1731           0 :                                         rTileInfo.aTileTopLeft.Y() + rTileSizePixel.Height()*nRemainderTilesY );
    1732           0 :     rTileInfo.aTileSizePixel   = Size( rTileSizePixel.Width()*nMSBFactor*nExponent,
    1733           0 :                                        rTileSizePixel.Height()*nMSBFactor*nExponent );
    1734           0 :     rTileInfo.nTilesEmptyX     = aTileInfo.nTilesEmptyX - nRemainderTilesX;
    1735           0 :     rTileInfo.nTilesEmptyY     = aTileInfo.nTilesEmptyY - nRemainderTilesY;
    1736             : 
    1737             :     // init output position
    1738           0 :     aCurrPos = aTileInfo.aNextTileTopLeft;
    1739             : 
    1740             :     // fill our drawing area. Fill possibly more, to create the next
    1741             :     // bigger tile size -> see bitmap extraction above. This does no
    1742             :     // harm, since everything right or below our actual area is
    1743             :     // overdrawn by our caller. Just in case we're in the last level,
    1744             :     // we don't draw beyond the right or bottom border.
    1745           0 :     for( nY=0; nY < aTileInfo.nTilesEmptyY && nY < nExponent*nMSBFactor; nY += nMSBFactor )
    1746             :     {
    1747           0 :         aCurrPos.X() = aTileInfo.aNextTileTopLeft.X();
    1748             : 
    1749           0 :         for( nX=0; nX < aTileInfo.nTilesEmptyX && nX < nExponent*nMSBFactor; nX += nMSBFactor )
    1750             :         {
    1751           0 :             if( bNoFirstTileDraw )
    1752           0 :                 bNoFirstTileDraw = false; // don't draw first tile position
    1753           0 :             else if( !aTmpGraphic.Draw( &rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr, nFlags ) )
    1754           0 :                 return false;
    1755             : 
    1756           0 :             aCurrPos.X() += aTileInfo.aTileSizePixel.Width();
    1757             :         }
    1758             : 
    1759           0 :         aCurrPos.Y() += aTileInfo.aTileSizePixel.Height();
    1760             :     }
    1761             : 
    1762             : #ifdef DBG_TEST
    1763             : //  rVDev.SetFillColor( COL_WHITE );
    1764             :     rVDev.SetFillColor();
    1765             :     rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) );
    1766             :     rVDev.DrawRect( Rectangle((rTileInfo.aTileTopLeft.X())*rTileSizePixel.Width(),
    1767             :                               (rTileInfo.aTileTopLeft.Y())*rTileSizePixel.Height(),
    1768             :                               (rTileInfo.aNextTileTopLeft.X())*rTileSizePixel.Width()-1,
    1769             :                               (rTileInfo.aNextTileTopLeft.Y())*rTileSizePixel.Height()-1) );
    1770             : #endif
    1771             : 
    1772           0 :     return true;
    1773             : }
    1774             : 
    1775           0 : bool GraphicObject::ImplDrawTiled( OutputDevice* pOut, const Rectangle& rArea, const Size& rSizePixel,
    1776             :                                    const Size& rOffset, const GraphicAttr* pAttr, sal_uLong nFlags, int nTileCacheSize1D )
    1777             : {
    1778             :     // how many tiles to generate per recursion step
    1779             :     enum{ SubdivisionExponent=2 };
    1780             : 
    1781           0 :     const MapMode   aOutMapMode( pOut->GetMapMode() );
    1782           0 :     const MapMode   aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
    1783           0 :     bool            bRet( false );
    1784             : 
    1785             :     // #i42643# Casting to Int64, to avoid integer overflow for
    1786             :     // huge-DPI output devices
    1787           0 :     if( GetGraphic().GetType() == GRAPHIC_BITMAP &&
    1788           0 :         static_cast<sal_Int64>(rSizePixel.Width()) * rSizePixel.Height() <
    1789             :         static_cast<sal_Int64>(nTileCacheSize1D)*nTileCacheSize1D )
    1790             :     {
    1791             :         // First combine very small bitmaps into a larger tile
    1792             :         // ===================================================
    1793             : 
    1794           0 :         VirtualDevice   aVDev;
    1795           0 :         const int       nNumTilesInCacheX( (nTileCacheSize1D + rSizePixel.Width()-1) / rSizePixel.Width() );
    1796           0 :         const int       nNumTilesInCacheY( (nTileCacheSize1D + rSizePixel.Height()-1) / rSizePixel.Height() );
    1797             : 
    1798           0 :         aVDev.SetOutputSizePixel( Size( nNumTilesInCacheX*rSizePixel.Width(),
    1799           0 :                                         nNumTilesInCacheY*rSizePixel.Height() ) );
    1800           0 :         aVDev.SetMapMode( aMapMode );
    1801             : 
    1802             :         // draw bitmap content
    1803           0 :         if( ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX,
    1804             :                                 nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) )
    1805             :         {
    1806           0 :             BitmapEx aTileBitmap( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) );
    1807             : 
    1808             :             // draw alpha content, if any
    1809           0 :             if( IsTransparent() )
    1810             :             {
    1811           0 :                 GraphicObject aAlphaGraphic;
    1812             : 
    1813           0 :                 if( GetGraphic().IsAlpha() )
    1814           0 :                     aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetAlpha().GetBitmap() );
    1815             :                 else
    1816           0 :                     aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetMask() );
    1817             : 
    1818           0 :                 if( aAlphaGraphic.ImplRenderTempTile( aVDev, SubdivisionExponent, nNumTilesInCacheX,
    1819             :                                                       nNumTilesInCacheY, rSizePixel, pAttr, nFlags ) )
    1820             :                 {
    1821             :                     // Combine bitmap and alpha/mask
    1822           0 :                     if( GetGraphic().IsAlpha() )
    1823             :                         aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(),
    1824           0 :                                                 AlphaMask( aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ) ) );
    1825             :                     else
    1826             :                         aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(),
    1827           0 :                                                 aVDev.GetBitmap( Point(0,0), aVDev.GetOutputSize() ).CreateMask( Color(COL_WHITE) ) );
    1828           0 :                 }
    1829             :             }
    1830             : 
    1831             :             // paint generated tile
    1832           0 :             GraphicObject aTmpGraphic( aTileBitmap );
    1833             :             bRet = aTmpGraphic.ImplDrawTiled( pOut, rArea,
    1834           0 :                                               aTileBitmap.GetSizePixel(),
    1835           0 :                                               rOffset, pAttr, nFlags, nTileCacheSize1D );
    1836           0 :         }
    1837             :     }
    1838             :     else
    1839             :     {
    1840           0 :         const Size      aOutOffset( pOut->LogicToPixel( rOffset, aOutMapMode ) );
    1841           0 :         const Rectangle aOutArea( pOut->LogicToPixel( rArea, aOutMapMode ) );
    1842             : 
    1843             :         // number of invisible (because out-of-area) tiles
    1844             :         int nInvisibleTilesX;
    1845             :         int nInvisibleTilesY;
    1846             : 
    1847             :         // round towards -infty for negative offset
    1848           0 :         if( aOutOffset.Width() < 0 )
    1849           0 :             nInvisibleTilesX = (aOutOffset.Width() - rSizePixel.Width() + 1) / rSizePixel.Width();
    1850             :         else
    1851           0 :             nInvisibleTilesX = aOutOffset.Width() / rSizePixel.Width();
    1852             : 
    1853             :         // round towards -infty for negative offset
    1854           0 :         if( aOutOffset.Height() < 0 )
    1855           0 :             nInvisibleTilesY = (aOutOffset.Height() - rSizePixel.Height() + 1) / rSizePixel.Height();
    1856             :         else
    1857           0 :             nInvisibleTilesY = aOutOffset.Height() / rSizePixel.Height();
    1858             : 
    1859             :         // origin from where to 'virtually' start drawing in pixel
    1860           0 :         const Point aOutOrigin( pOut->LogicToPixel( Point( rArea.Left() - rOffset.Width(),
    1861           0 :                                                            rArea.Top() - rOffset.Height() ) ) );
    1862             :         // position in pixel from where to really start output
    1863           0 :         const Point aOutStart( aOutOrigin.X() + nInvisibleTilesX*rSizePixel.Width(),
    1864           0 :                                aOutOrigin.Y() + nInvisibleTilesY*rSizePixel.Height() );
    1865             : 
    1866           0 :         pOut->Push( PUSH_CLIPREGION );
    1867           0 :         pOut->IntersectClipRegion( rArea );
    1868             : 
    1869             :         // Paint all tiles
    1870             :         // ===============
    1871             : 
    1872             :         bRet = ImplDrawTiled( *pOut, aOutStart,
    1873           0 :                               (aOutArea.GetWidth() + aOutArea.Left() - aOutStart.X() + rSizePixel.Width() - 1) / rSizePixel.Width(),
    1874           0 :                               (aOutArea.GetHeight() + aOutArea.Top() - aOutStart.Y() + rSizePixel.Height() - 1) / rSizePixel.Height(),
    1875           0 :                               rSizePixel, pAttr, nFlags );
    1876             : 
    1877           0 :         pOut->Pop();
    1878             :     }
    1879             : 
    1880           0 :     return bRet;
    1881             : }
    1882             : 
    1883           0 : bool GraphicObject::ImplDrawTiled( OutputDevice& rOut, const Point& rPosPixel,
    1884             :                                    int nNumTilesX, int nNumTilesY,
    1885             :                                    const Size& rTileSizePixel, const GraphicAttr* pAttr, sal_uLong nFlags )
    1886             : {
    1887           0 :     Point   aCurrPos( rPosPixel );
    1888           0 :     Size    aTileSizeLogic( rOut.PixelToLogic( rTileSizePixel ) );
    1889             :     int     nX, nY;
    1890             : 
    1891             :     // #107607# Use logical coordinates for metafile playing, too
    1892           0 :     bool    bDrawInPixel( rOut.GetConnectMetaFile() == NULL && GRAPHIC_BITMAP == GetType() );
    1893           0 :     bool    bRet = false;
    1894             : 
    1895             :     // #105229# Switch off mapping (converting to logic and back to
    1896             :     // pixel might cause roundoff errors)
    1897           0 :     bool bOldMap( rOut.IsMapModeEnabled() );
    1898             : 
    1899           0 :     if( bDrawInPixel )
    1900           0 :         rOut.EnableMapMode( sal_False );
    1901             : 
    1902           0 :     for( nY=0; nY < nNumTilesY; ++nY )
    1903             :     {
    1904           0 :         aCurrPos.X() = rPosPixel.X();
    1905             : 
    1906           0 :         for( nX=0; nX < nNumTilesX; ++nX )
    1907             :         {
    1908             :             // #105229# work with pixel coordinates here, mapping is disabled!
    1909             :             // #104004# don't disable mapping for metafile recordings
    1910             :             // #108412# don't quit the loop if one draw fails
    1911             : 
    1912             :             // update return value. This method should return true, if
    1913             :             // at least one of the looped Draws succeeded.
    1914             :             bRet |= Draw( &rOut,
    1915             :                           bDrawInPixel ? aCurrPos : rOut.PixelToLogic( aCurrPos ),
    1916             :                           bDrawInPixel ? rTileSizePixel : aTileSizeLogic,
    1917           0 :                           pAttr, nFlags );
    1918             : 
    1919           0 :             aCurrPos.X() += rTileSizePixel.Width();
    1920             :         }
    1921             : 
    1922           0 :         aCurrPos.Y() += rTileSizePixel.Height();
    1923             :     }
    1924             : 
    1925           0 :     if( bDrawInPixel )
    1926           0 :         rOut.EnableMapMode( bOldMap );
    1927             : 
    1928           0 :     return bRet;
    1929             : }
    1930             : 
    1931           0 : void GraphicObject::ImplTransformBitmap( BitmapEx&          rBmpEx,
    1932             :                                          const GraphicAttr& rAttr,
    1933             :                                          const Size&        rCropLeftTop,
    1934             :                                          const Size&        rCropRightBottom,
    1935             :                                          const Rectangle&   rCropRect,
    1936             :                                          const Size&        rDstSize,
    1937             :                                          sal_Bool               bEnlarge ) const
    1938             : {
    1939             :     // #107947# Extracted from svdograf.cxx
    1940             : 
    1941             :     // #104115# Crop the bitmap
    1942           0 :     if( rAttr.IsCropped() )
    1943             :     {
    1944           0 :         rBmpEx.Crop( rCropRect );
    1945             : 
    1946             :         // #104115# Negative crop sizes mean: enlarge bitmap and pad
    1947           0 :         if( bEnlarge && (
    1948           0 :             rCropLeftTop.Width() < 0 ||
    1949           0 :             rCropLeftTop.Height() < 0 ||
    1950           0 :             rCropRightBottom.Width() < 0 ||
    1951           0 :             rCropRightBottom.Height() < 0 ) )
    1952             :         {
    1953           0 :             Size aBmpSize( rBmpEx.GetSizePixel() );
    1954           0 :             sal_Int32 nPadLeft( rCropLeftTop.Width() < 0 ? -rCropLeftTop.Width() : 0 );
    1955           0 :             sal_Int32 nPadTop( rCropLeftTop.Height() < 0 ? -rCropLeftTop.Height() : 0 );
    1956           0 :             sal_Int32 nPadTotalWidth( aBmpSize.Width() + nPadLeft + (rCropRightBottom.Width() < 0 ? -rCropRightBottom.Width() : 0) );
    1957           0 :             sal_Int32 nPadTotalHeight( aBmpSize.Height() + nPadTop + (rCropRightBottom.Height() < 0 ? -rCropRightBottom.Height() : 0) );
    1958             : 
    1959           0 :             BitmapEx aBmpEx2;
    1960             : 
    1961           0 :             if( rBmpEx.IsTransparent() )
    1962             :             {
    1963           0 :                 if( rBmpEx.IsAlpha() )
    1964           0 :                     aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetAlpha() );
    1965             :                 else
    1966           0 :                     aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetMask() );
    1967             :             }
    1968             :             else
    1969             :             {
    1970             :                 // #104115# Generate mask bitmap and init to zero
    1971           0 :                 Bitmap aMask( aBmpSize, 1 );
    1972           0 :                 aMask.Erase( Color(0,0,0) );
    1973             : 
    1974             :                 // #104115# Always generate transparent bitmap, we need the border transparent
    1975           0 :                 aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), aMask );
    1976             : 
    1977             :                 // #104115# Add opaque mask to source bitmap, otherwise the destination remains transparent
    1978           0 :                 rBmpEx = aBmpEx2;
    1979             :             }
    1980             : 
    1981           0 :             aBmpEx2.SetSizePixel( Size(nPadTotalWidth, nPadTotalHeight) );
    1982           0 :             aBmpEx2.Erase( Color(0xFF,0,0,0) );
    1983           0 :             aBmpEx2.CopyPixel( Rectangle( Point(nPadLeft, nPadTop), aBmpSize ), Rectangle( Point(0, 0), aBmpSize ), &rBmpEx );
    1984           0 :             rBmpEx = aBmpEx2;
    1985             :         }
    1986             :     }
    1987             : 
    1988           0 :     const Size  aSizePixel( rBmpEx.GetSizePixel() );
    1989             : 
    1990           0 :     if( rAttr.GetRotation() != 0 && !IsAnimated() )
    1991             :     {
    1992           0 :         if( aSizePixel.Width() && aSizePixel.Height() && rDstSize.Width() && rDstSize.Height() )
    1993             :         {
    1994           0 :             double fSrcWH = (double) aSizePixel.Width() / aSizePixel.Height();
    1995           0 :             double fDstWH = (double) rDstSize.Width() / rDstSize.Height();
    1996           0 :             double fScaleX = 1.0, fScaleY = 1.0;
    1997             : 
    1998             :             // always choose scaling to shrink bitmap
    1999           0 :             if( fSrcWH < fDstWH )
    2000           0 :                 fScaleY = aSizePixel.Width() / ( fDstWH * aSizePixel.Height() );
    2001             :             else
    2002           0 :                 fScaleX = fDstWH * aSizePixel.Height() / aSizePixel.Width();
    2003             : 
    2004           0 :             rBmpEx.Scale( fScaleX, fScaleY );
    2005             :         }
    2006             :     }
    2007           0 : }
    2008             : 
    2009             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10