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

Generated by: LCOV version 1.11