LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/source/gdi - bitmapex.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 410 615 66.7 %
Date: 2013-07-09 Functions: 39 53 73.6 %
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 <ctype.h>
      21             : #include <rtl/crc.h>
      22             : #include <rtl/strbuf.hxx>
      23             : 
      24             : #include <tools/stream.hxx>
      25             : #include <tools/debug.hxx>
      26             : #include <tools/rc.h>
      27             : #include <vcl/salbtype.hxx>
      28             : #include <vcl/outdev.hxx>
      29             : #include <vcl/alpha.hxx>
      30             : #include <vcl/bitmapex.hxx>
      31             : #include <vcl/dibtools.hxx>
      32             : #include <vcl/pngread.hxx>
      33             : #include <vcl/svapp.hxx>
      34             : #include <vcl/bmpacc.hxx>
      35             : #include <vcl/virdev.hxx>
      36             : 
      37             : #include <image.h>
      38             : #include <impimagetree.hxx>
      39             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      40             : 
      41             : // BitmapEx::Create
      42             : #include <salbmp.hxx>
      43             : #include <salinst.hxx>
      44             : #include <svdata.hxx>
      45             : #include <com/sun/star/beans/XFastPropertySet.hpp>
      46             : using namespace ::com::sun::star;
      47             : 
      48      441697 : BitmapEx::BitmapEx() :
      49             :         eTransparent( TRANSPARENT_NONE ),
      50      441697 :         bAlpha      ( sal_False )
      51             : {
      52      441697 : }
      53             : 
      54      613171 : BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
      55             :         aBitmap             ( rBitmapEx.aBitmap ),
      56             :         aMask               ( rBitmapEx.aMask ),
      57             :         aBitmapSize         ( rBitmapEx.aBitmapSize ),
      58             :         aTransparentColor   ( rBitmapEx.aTransparentColor ),
      59             :         eTransparent        ( rBitmapEx.eTransparent ),
      60      613171 :         bAlpha              ( rBitmapEx.bAlpha )
      61             : {
      62      613171 : }
      63             : 
      64        1926 : BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize ) :
      65             :         eTransparent( TRANSPARENT_NONE ),
      66        1926 :         bAlpha      ( sal_False )
      67             : {
      68        1926 :     if( rBitmapEx.IsEmpty() )
      69        1941 :         return;
      70             : 
      71        1911 :     aBitmap = Bitmap( aSize, rBitmapEx.aBitmap.GetBitCount() );
      72        1911 :     aBitmapSize = aSize;
      73        1911 :     if( rBitmapEx.IsAlpha() )
      74             :     {
      75        1755 :         bAlpha = sal_True;
      76        1755 :         aMask = AlphaMask( aSize ).ImplGetBitmap();
      77             :     }
      78         156 :     else if( rBitmapEx.IsTransparent() )
      79         156 :         aMask = Bitmap( aSize, rBitmapEx.aMask.GetBitCount() );
      80             : 
      81        1911 :     Rectangle aDestRect( Point( 0, 0 ), aSize );
      82        1911 :     Rectangle aSrcRect( aSrc, aSize );
      83        1911 :     CopyPixel( aDestRect, aSrcRect, &rBitmapEx );
      84             : }
      85             : 
      86       13773 : BitmapEx::BitmapEx( const ResId& rResId ) :
      87             :         eTransparent( TRANSPARENT_NONE ),
      88       13773 :         bAlpha      ( sal_False )
      89             : {
      90       13773 :     static ImplImageTreeSingletonRef    aImageTree;
      91       13773 :     ResMgr*                             pResMgr = NULL;
      92             : 
      93       13773 :     ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
      94       13773 :     pResMgr->ReadLong();
      95       13773 :     pResMgr->ReadLong();
      96             : 
      97       13773 :     const String aFileName( pResMgr->ReadString() );
      98       27546 :     OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName();
      99             : 
     100       13773 :     if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this, true ) )
     101             :     {
     102             : #ifdef DBG_UTIL
     103             :         OStringBuffer aErrorStr(
     104             :             "BitmapEx::BitmapEx( const ResId& rResId ): could not load image <");
     105             :         aErrorStr.append(OUStringToOString(aFileName, RTL_TEXTENCODING_ASCII_US)).append('>');
     106             :         OSL_FAIL(aErrorStr.getStr());
     107             : #endif
     108       13773 :     }
     109       13773 : }
     110             : 
     111        5246 : BitmapEx::BitmapEx( const Bitmap& rBmp ) :
     112             :         aBitmap     ( rBmp ),
     113        5246 :         aBitmapSize ( aBitmap.GetSizePixel() ),
     114             :         eTransparent( TRANSPARENT_NONE ),
     115       10492 :         bAlpha      ( sal_False )
     116             : {
     117        5246 : }
     118             : 
     119        4126 : BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
     120             :         aBitmap         ( rBmp ),
     121             :         aMask           ( rMask ),
     122        4126 :         aBitmapSize     ( aBitmap.GetSizePixel() ),
     123        4126 :         eTransparent    ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
     124       12378 :         bAlpha          ( sal_False )
     125             : {
     126        4126 :     if(!!aBitmap && !!aMask && aBitmap.GetSizePixel() != aMask.GetSizePixel())
     127             :     {
     128             :         OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)");
     129           0 :         aMask.Scale(aBitmap.GetSizePixel());
     130             :     }
     131             : 
     132             :     // Ensure a mask is exactly one bit deep
     133        4126 :     if( !!aMask && aMask.GetBitCount() != 1 )
     134             :     {
     135             :         OSL_TRACE("BitmapEx: forced mask to monochrome");
     136           7 :         aMask.ImplMakeMono( 255 );
     137             :     }
     138        4126 : }
     139             : 
     140       24934 : BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
     141             :         aBitmap         ( rBmp ),
     142       24934 :         aMask           ( rAlphaMask.ImplGetBitmap() ),
     143       24934 :         aBitmapSize     ( aBitmap.GetSizePixel() ),
     144       24934 :         eTransparent    ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
     145       99736 :         bAlpha          ( !rAlphaMask ? sal_False : sal_True )
     146             : {
     147       24934 :     if(!!aBitmap && !!aMask && aBitmap.GetSizePixel() != aMask.GetSizePixel())
     148             :     {
     149             :         OSL_ENSURE(false, "Alpha size differs from Bitmap size, corrected Mask (!)");
     150           0 :         aMask.Scale(rBmp.GetSizePixel());
     151             :     }
     152             : 
     153             :     // #i75531# the workaround below can go when
     154             :     // X11SalGraphics::drawAlphaBitmap()'s render acceleration
     155             :     // can handle the bitmap depth mismatch directly
     156       24934 :     if( aBitmap.GetBitCount() < aMask.GetBitCount() )
     157          32 :         aBitmap.Convert( BMP_CONVERSION_24BIT );
     158       24934 : }
     159             : 
     160         136 : BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
     161             :         aBitmap             ( rBmp ),
     162         136 :         aBitmapSize         ( aBitmap.GetSizePixel() ),
     163             :         aTransparentColor   ( rTransparentColor ),
     164             :         eTransparent        ( TRANSPARENT_BITMAP ),
     165         272 :         bAlpha              ( sal_False )
     166             : {
     167         136 :     aMask = aBitmap.CreateMask( aTransparentColor );
     168             : 
     169             :     DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(),
     170             :                 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
     171         136 : }
     172             : 
     173     1104414 : BitmapEx::~BitmapEx()
     174             : {
     175     1104414 : }
     176             : 
     177      184791 : BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
     178             : {
     179      184791 :     if( &rBitmapEx != this )
     180             :     {
     181      184791 :         aBitmap = rBitmapEx.aBitmap;
     182      184791 :         aMask = rBitmapEx.aMask;
     183      184791 :         aBitmapSize = rBitmapEx.aBitmapSize;
     184      184791 :         aTransparentColor = rBitmapEx.aTransparentColor;
     185      184791 :         eTransparent = rBitmapEx.eTransparent;
     186      184791 :         bAlpha = rBitmapEx.bAlpha;
     187             :     }
     188             : 
     189      184791 :     return *this;
     190             : }
     191             : 
     192        1878 : sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
     193             : {
     194        1878 :     if( eTransparent != rBitmapEx.eTransparent )
     195           0 :         return sal_False;
     196             : 
     197        1878 :     if( aBitmap != rBitmapEx.aBitmap )
     198           2 :         return sal_False;
     199             : 
     200        1876 :     if( aBitmapSize != rBitmapEx.aBitmapSize )
     201           0 :         return sal_False;
     202             : 
     203        1876 :     if( eTransparent == TRANSPARENT_NONE )
     204         296 :         return sal_True;
     205             : 
     206        1580 :     if( eTransparent == TRANSPARENT_COLOR )
     207           0 :         return aTransparentColor == rBitmapEx.aTransparentColor;
     208             : 
     209        1580 :     return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
     210             : }
     211             : 
     212           0 : sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
     213             : {
     214           0 :     return( rBmpEx.eTransparent == eTransparent &&
     215           0 :             rBmpEx.bAlpha == bAlpha &&
     216           0 :             rBmpEx.aBitmap.IsEqual( aBitmap ) &&
     217           0 :             rBmpEx.aMask.IsEqual( aMask ) );
     218             : }
     219             : 
     220      445429 : sal_Bool BitmapEx::IsEmpty() const
     221             : {
     222      445429 :     return( aBitmap.IsEmpty() && aMask.IsEmpty() );
     223             : }
     224             : 
     225      238967 : void BitmapEx::SetEmpty()
     226             : {
     227      238967 :     aBitmap.SetEmpty();
     228      238967 :     aMask.SetEmpty();
     229      238967 :     eTransparent = TRANSPARENT_NONE;
     230      238967 :     bAlpha = sal_False;
     231      238967 : }
     232             : 
     233      204597 : void BitmapEx::Clear()
     234             : {
     235      204597 :     SetEmpty();
     236      204597 : }
     237             : 
     238      332023 : sal_Bool BitmapEx::IsTransparent() const
     239             : {
     240      332023 :     return( eTransparent != TRANSPARENT_NONE );
     241             : }
     242             : 
     243      323569 : sal_Bool BitmapEx::IsAlpha() const
     244             : {
     245      323569 :     return( IsTransparent() && bAlpha );
     246             : }
     247             : 
     248      163648 : Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
     249             : {
     250      163648 :     Bitmap aRetBmp( aBitmap );
     251             : 
     252      163648 :     if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
     253             :     {
     254           0 :         Bitmap aTempMask;
     255             : 
     256           0 :         if( eTransparent == TRANSPARENT_COLOR )
     257           0 :             aTempMask = aBitmap.CreateMask( aTransparentColor );
     258             :         else
     259           0 :             aTempMask = aMask;
     260             : 
     261           0 :         if( !IsAlpha() )
     262           0 :             aRetBmp.Replace( aTempMask, *pTransReplaceColor );
     263             :         else
     264           0 :             aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
     265             :     }
     266             : 
     267      163648 :     return aRetBmp;
     268             : }
     269             : 
     270         455 : Bitmap BitmapEx::GetMask() const
     271             : {
     272         455 :     Bitmap aRet( aMask );
     273             : 
     274         455 :     if( IsAlpha() )
     275           2 :         aRet.ImplMakeMono( 255 );
     276             : 
     277         455 :     return aRet;
     278             : }
     279             : 
     280      141093 : AlphaMask BitmapEx::GetAlpha() const
     281             : {
     282      141093 :     if( IsAlpha() )
     283             :     {
     284      141093 :         AlphaMask aAlpha;
     285      141093 :         aAlpha.ImplSetBitmap( aMask );
     286      141093 :         return aAlpha;
     287             :     }
     288             :     else
     289             :     {
     290           0 :         return aMask;
     291             :     }
     292             : }
     293             : 
     294         964 : sal_uLong BitmapEx::GetSizeBytes() const
     295             : {
     296         964 :     sal_uLong nSizeBytes = aBitmap.GetSizeBytes();
     297             : 
     298         964 :     if( eTransparent == TRANSPARENT_BITMAP )
     299         142 :         nSizeBytes += aMask.GetSizeBytes();
     300             : 
     301         964 :     return nSizeBytes;
     302             : }
     303             : 
     304         530 : sal_uLong BitmapEx::GetChecksum() const
     305             : {
     306         530 :     sal_uInt32  nCrc = aBitmap.GetChecksum();
     307             :     SVBT32      aBT32;
     308             : 
     309         530 :     UInt32ToSVBT32( (long) eTransparent, aBT32 );
     310         530 :     nCrc = rtl_crc32( nCrc, aBT32, 4 );
     311             : 
     312         530 :     UInt32ToSVBT32( (long) bAlpha, aBT32 );
     313         530 :     nCrc = rtl_crc32( nCrc, aBT32, 4 );
     314             : 
     315         530 :     if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
     316             :     {
     317          90 :         UInt32ToSVBT32( aMask.GetChecksum(), aBT32 );
     318          90 :         nCrc = rtl_crc32( nCrc, aBT32, 4 );
     319             :     }
     320             : 
     321         530 :     return nCrc;
     322             : }
     323             : 
     324             : // ------------------------------------------------------------------
     325             : 
     326        1341 : void BitmapEx::SetSizePixel( const Size& rNewSize, sal_uInt32 nScaleFlag )
     327             : {
     328        1341 :     if(GetSizePixel() != rNewSize)
     329             :     {
     330          53 :         Scale( rNewSize, nScaleFlag );
     331             :     }
     332        1341 : }
     333             : 
     334           0 : sal_Bool BitmapEx::Invert()
     335             : {
     336           0 :     sal_Bool bRet = sal_False;
     337             : 
     338           0 :     if( !!aBitmap )
     339             :     {
     340           0 :         bRet = aBitmap.Invert();
     341             : 
     342           0 :         if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
     343           0 :             aTransparentColor = BitmapColor( aTransparentColor ).Invert();
     344             :     }
     345             : 
     346           0 :     return bRet;
     347             : }
     348             : 
     349           0 : sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags )
     350             : {
     351           0 :     sal_Bool bRet = sal_False;
     352             : 
     353           0 :     if( !!aBitmap )
     354             :     {
     355           0 :         bRet = aBitmap.Mirror( nMirrorFlags );
     356             : 
     357           0 :         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     358           0 :             aMask.Mirror( nMirrorFlags );
     359             :     }
     360             : 
     361           0 :     return bRet;
     362             : }
     363             : 
     364             : // ------------------------------------------------------------------
     365             : 
     366       24749 : sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
     367             : {
     368       24749 :     sal_Bool bRet = sal_False;
     369             : 
     370       24749 :     if( !!aBitmap )
     371             :     {
     372       24325 :         bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
     373             : 
     374       24325 :         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     375             :         {
     376       24195 :             aMask.Scale( rScaleX, rScaleY, nScaleFlag );
     377             :         }
     378             : 
     379       24325 :         aBitmapSize = aBitmap.GetSizePixel();
     380             : 
     381             :         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
     382             :                     "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
     383             :     }
     384             : 
     385       24749 :     return bRet;
     386             : }
     387             : 
     388             : // ------------------------------------------------------------------------
     389             : 
     390        1152 : sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
     391             : {
     392             :     sal_Bool bRet;
     393             : 
     394        3456 :     if( aBitmapSize.Width() && aBitmapSize.Height() &&
     395        1558 :         ( rNewSize.Width()  != aBitmapSize.Width() ||
     396         406 :           rNewSize.Height() != aBitmapSize.Height() ) )
     397             :     {
     398        1152 :         bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
     399        1152 :                       (double) rNewSize.Height() / aBitmapSize.Height(),
     400        2304 :                       nScaleFlag );
     401             :     }
     402             :     else
     403           0 :         bRet = sal_True;
     404             : 
     405        1152 :     return bRet;
     406             : }
     407             : 
     408           0 : sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
     409             : {
     410           0 :     sal_Bool bRet = sal_False;
     411             : 
     412           0 :     if( !!aBitmap )
     413             :     {
     414           0 :         const bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
     415             : 
     416           0 :         if( bTransRotate )
     417             :         {
     418           0 :             if( eTransparent == TRANSPARENT_COLOR )
     419           0 :                 bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
     420             :             else
     421             :             {
     422           0 :                 bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
     423             : 
     424           0 :                 if( eTransparent == TRANSPARENT_NONE )
     425             :                 {
     426           0 :                     aMask = Bitmap( aBitmapSize, 1 );
     427           0 :                     aMask.Erase( COL_BLACK );
     428           0 :                     eTransparent = TRANSPARENT_BITMAP;
     429             :                 }
     430             : 
     431           0 :                 if( bRet && !!aMask )
     432           0 :                     aMask.Rotate( nAngle10, COL_WHITE );
     433             :             }
     434             :         }
     435             :         else
     436             :         {
     437           0 :             bRet = aBitmap.Rotate( nAngle10, rFillColor );
     438             : 
     439           0 :             if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     440           0 :                 aMask.Rotate( nAngle10, COL_WHITE );
     441             :         }
     442             : 
     443           0 :         aBitmapSize = aBitmap.GetSizePixel();
     444             : 
     445             :         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
     446             :                     "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." );
     447             :     }
     448             : 
     449           0 :     return bRet;
     450             : }
     451             : 
     452        1041 : sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel )
     453             : {
     454        1041 :     sal_Bool bRet = sal_False;
     455             : 
     456        1041 :     if( !!aBitmap )
     457             :     {
     458         769 :         bRet = aBitmap.Crop( rRectPixel );
     459             : 
     460         769 :         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     461         617 :             aMask.Crop( rRectPixel );
     462             : 
     463         769 :         aBitmapSize = aBitmap.GetSizePixel();
     464             : 
     465             :         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
     466             :                     "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." );
     467             :     }
     468             : 
     469        1041 :     return bRet;
     470             : }
     471             : 
     472         468 : sal_Bool BitmapEx::Convert( BmpConversion eConversion )
     473             : {
     474         468 :     return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False );
     475             : }
     476             : 
     477           0 : sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
     478             : {
     479           0 :     return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False );
     480             : }
     481             : 
     482           0 : sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent )
     483             : {
     484           0 :     sal_Bool bRet = sal_False;
     485             : 
     486           0 :     if( !!aBitmap )
     487             :     {
     488           0 :         bRet = aBitmap.Expand( nDX, nDY, pInitColor );
     489             : 
     490           0 :         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     491             :         {
     492           0 :             Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
     493           0 :             aMask.Expand( nDX, nDY, &aColor );
     494             :         }
     495             : 
     496           0 :         aBitmapSize = aBitmap.GetSizePixel();
     497             : 
     498             :         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
     499             :                     "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." );
     500             :     }
     501             : 
     502           0 :     return bRet;
     503             : }
     504             : 
     505        4560 : sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
     506             :                           const BitmapEx* pBmpExSrc )
     507             : {
     508        4560 :     sal_Bool bRet = sal_False;
     509             : 
     510        4560 :     if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
     511             :     {
     512         447 :         if( !aBitmap.IsEmpty() )
     513             :         {
     514           0 :             bRet = aBitmap.CopyPixel( rRectDst, rRectSrc );
     515             : 
     516           0 :             if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     517           0 :                 aMask.CopyPixel( rRectDst, rRectSrc );
     518             :         }
     519             :     }
     520             :     else
     521             :     {
     522        4113 :         if( !aBitmap.IsEmpty() )
     523             :         {
     524        4113 :             bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap );
     525             : 
     526        4113 :             if( bRet )
     527             :             {
     528        4113 :                 if( pBmpExSrc->IsAlpha() )
     529             :                 {
     530        3423 :                     if( IsAlpha() )
     531             :                         // cast to use the optimized AlphaMask::CopyPixel
     532        1668 :                         ((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask );
     533        1755 :                     else if( IsTransparent() )
     534             :                     {
     535           0 :                         AlphaMask* pAlpha = new AlphaMask( aMask );
     536             : 
     537           0 :                         aMask = pAlpha->ImplGetBitmap();
     538           0 :                         delete pAlpha;
     539           0 :                         bAlpha = sal_True;
     540           0 :                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
     541             :                     }
     542             :                     else
     543             :                     {
     544        1755 :                         sal_uInt8   cBlack = 0;
     545        1755 :                         AlphaMask*  pAlpha = new AlphaMask( GetSizePixel(), &cBlack );
     546             : 
     547        1755 :                         aMask = pAlpha->ImplGetBitmap();
     548        1755 :                         delete pAlpha;
     549        1755 :                         eTransparent = TRANSPARENT_BITMAP;
     550        1755 :                         bAlpha = sal_True;
     551        1755 :                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
     552             :                     }
     553             :                 }
     554         690 :                 else if( pBmpExSrc->IsTransparent() )
     555             :                 {
     556         156 :                     if( IsAlpha() )
     557             :                     {
     558           0 :                         AlphaMask aAlpha( pBmpExSrc->aMask );
     559           0 :                         aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
     560             :                     }
     561         156 :                     else if( IsTransparent() )
     562           0 :                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
     563             :                     else
     564             :                     {
     565         156 :                         aMask = Bitmap( GetSizePixel(), 1 );
     566         156 :                         aMask.Erase( Color( COL_BLACK ) );
     567         156 :                         eTransparent = TRANSPARENT_BITMAP;
     568         156 :                         aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
     569             :                     }
     570             :                 }
     571         534 :                 else if( IsAlpha() )
     572             :                 {
     573         534 :                     sal_uInt8         cBlack = 0;
     574         534 :                     const AlphaMask   aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack );
     575             : 
     576         534 :                     aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
     577             :                 }
     578           0 :                 else if( IsTransparent() )
     579             :                 {
     580           0 :                     Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 );
     581             : 
     582           0 :                     aMaskSrc.Erase( Color( COL_BLACK ) );
     583           0 :                     aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
     584             :                 }
     585             :             }
     586             :         }
     587             :     }
     588             : 
     589        4560 :     return bRet;
     590             : }
     591             : 
     592        1049 : sal_Bool BitmapEx::Erase( const Color& rFillColor )
     593             : {
     594        1049 :     sal_Bool bRet = sal_False;
     595             : 
     596        1049 :     if( !!aBitmap )
     597             :     {
     598         602 :         bRet = aBitmap.Erase( rFillColor );
     599             : 
     600         602 :         if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
     601             :         {
     602             :             // Respect transparency on fill color
     603         602 :             if( rFillColor.GetTransparency() )
     604             :             {
     605         602 :                 const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
     606         602 :                 aMask.Erase( aFill );
     607             :             }
     608             :             else
     609             :             {
     610           0 :                 const Color aBlack( COL_BLACK );
     611           0 :                 aMask.Erase( aBlack );
     612             :             }
     613             :         }
     614             :     }
     615             : 
     616        1049 :     return bRet;
     617             : }
     618             : 
     619           0 : sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags )
     620             : {
     621           0 :     return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False );
     622             : }
     623             : 
     624         585 : sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
     625             : {
     626         585 :     return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False );
     627             : }
     628             : 
     629          22 : sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols )
     630             : {
     631          22 :     return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False );
     632             : }
     633             : 
     634           0 : sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
     635             :                        short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
     636             :                        double fGamma, sal_Bool bInvert )
     637             : {
     638           0 :     return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
     639             :                                         nChannelRPercent, nChannelGPercent, nChannelBPercent,
     640           0 :                                         fGamma, bInvert ) : sal_False );
     641             : }
     642             : 
     643           0 : sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
     644             : {
     645           0 :     return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False );
     646             : }
     647             : 
     648           0 : void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
     649             : {
     650           0 :     pOutDev->DrawBitmapEx( rDestPt, *this );
     651           0 : }
     652             : 
     653           0 : void BitmapEx::Draw( OutputDevice* pOutDev,
     654             :                      const Point& rDestPt, const Size& rDestSize ) const
     655             : {
     656           0 :     pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
     657           0 : }
     658             : 
     659           0 : BitmapEx BitmapEx:: AutoScaleBitmap(BitmapEx & aBitmap, const long aStandardSize)
     660             : {
     661           0 :     Point aEmptyPoint(0,0);
     662           0 :     double imgposX = 0;
     663           0 :     double imgposY = 0;
     664           0 :     BitmapEx  aRet = aBitmap;
     665           0 :     double imgOldWidth = aRet.GetSizePixel().Width();
     666           0 :     double imgOldHeight =aRet.GetSizePixel().Height();
     667             : 
     668           0 :     Size aScaledSize;
     669           0 :     if (imgOldWidth >= aStandardSize || imgOldHeight >= aStandardSize)
     670             :     {
     671           0 :         sal_Int32 imgNewWidth = 0;
     672           0 :         sal_Int32 imgNewHeight = 0;
     673           0 :         if (imgOldWidth >= imgOldHeight)
     674             :         {
     675           0 :             imgNewWidth = aStandardSize;
     676           0 :             imgNewHeight = sal_Int32(imgOldHeight / (imgOldWidth / aStandardSize) + 0.5);
     677           0 :             imgposX = 0;
     678           0 :             imgposY = (aStandardSize - (imgOldHeight / (imgOldWidth / aStandardSize) + 0.5)) / 2 + 0.5;
     679             :         }
     680             :         else
     681             :         {
     682           0 :             imgNewHeight = aStandardSize;
     683           0 :             imgNewWidth = sal_Int32(imgOldWidth / (imgOldHeight / aStandardSize) + 0.5);
     684           0 :             imgposY = 0;
     685           0 :             imgposX = (aStandardSize - (imgOldWidth / (imgOldHeight / aStandardSize) + 0.5)) / 2 + 0.5;
     686             :         }
     687             : 
     688           0 :         aScaledSize = Size( imgNewWidth, imgNewHeight );
     689           0 :         aRet.Scale( aScaledSize, BMP_SCALE_BESTQUALITY );
     690             :     }
     691             :     else
     692             :     {
     693           0 :         imgposX = (aStandardSize - imgOldWidth) / 2 + 0.5;
     694           0 :         imgposY = (aStandardSize - imgOldHeight) / 2 + 0.5;
     695             :     }
     696             : 
     697           0 :     Size aStdSize( aStandardSize, aStandardSize );
     698           0 :     Rectangle aRect(aEmptyPoint, aStdSize );
     699             : 
     700           0 :     VirtualDevice aVirDevice( *Application::GetDefaultDevice(), 0, 1 );
     701           0 :     aVirDevice.SetOutputSizePixel( aStdSize );
     702           0 :     aVirDevice.SetFillColor( COL_TRANSPARENT );
     703           0 :     aVirDevice.SetLineColor( COL_TRANSPARENT );
     704             : 
     705             :     // Draw a rect into virDevice
     706           0 :     aVirDevice.DrawRect( aRect );
     707           0 :     Point aPointPixel( (long)imgposX, (long)imgposY );
     708           0 :     aVirDevice.DrawBitmapEx( aPointPixel, aRet );
     709           0 :     aRet = aVirDevice.GetBitmapEx( aEmptyPoint, aStdSize );
     710             : 
     711           0 :     return aRet;
     712             : }
     713             : 
     714           0 : sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
     715             : {
     716           0 :     sal_uInt8 nTransparency(0xff);
     717             : 
     718           0 :     if(!aBitmap.IsEmpty())
     719             :     {
     720           0 :         if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height())
     721             :         {
     722           0 :             switch(eTransparent)
     723             :             {
     724             :                 case TRANSPARENT_NONE:
     725             :                 {
     726             :                     // Not transparent, ergo all covered
     727           0 :                     nTransparency = 0x00;
     728           0 :                     break;
     729             :                 }
     730             :                 case TRANSPARENT_COLOR:
     731             :                 {
     732           0 :                     Bitmap aTestBitmap(aBitmap);
     733           0 :                     BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
     734             : 
     735           0 :                     if(pRead)
     736             :                     {
     737           0 :                         const Color aColor = pRead->GetColor(nY, nX);
     738             : 
     739             :                         // If color is not equal to TransparentColor, we are not transparent
     740           0 :                         if(aColor != aTransparentColor)
     741             :                         {
     742           0 :                             nTransparency = 0x00;
     743             :                         }
     744             : 
     745           0 :                         aTestBitmap.ReleaseAccess(pRead);
     746             :                     }
     747           0 :                     break;
     748             :                 }
     749             :                 case TRANSPARENT_BITMAP:
     750             :                 {
     751           0 :                     if(!aMask.IsEmpty())
     752             :                     {
     753           0 :                         Bitmap aTestBitmap(aMask);
     754           0 :                         BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
     755             : 
     756           0 :                         if(pRead)
     757             :                         {
     758           0 :                             const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
     759             : 
     760           0 :                             if(bAlpha)
     761             :                             {
     762           0 :                                 nTransparency = aBitmapColor.GetIndex();
     763             :                             }
     764             :                             else
     765             :                             {
     766           0 :                                 if(0x00 == aBitmapColor.GetIndex())
     767             :                                 {
     768           0 :                                     nTransparency = 0x00;
     769             :                                 }
     770             :                             }
     771             : 
     772           0 :                             aTestBitmap.ReleaseAccess(pRead);
     773           0 :                         }
     774             :                     }
     775           0 :                     break;
     776             :                 }
     777             :             }
     778             :         }
     779             :     }
     780             : 
     781           0 :     return nTransparency;
     782             : }
     783             : 
     784             : // Shift alpha transparent pixels between cppcanvas/ implementations
     785             : // and vcl in a generally grotesque and under-performing fashion
     786           0 : bool BitmapEx::Create( const ::com::sun::star::uno::Reference<
     787             :                        ::com::sun::star::rendering::XBitmapCanvas > &xBitmapCanvas,
     788             :                        const Size &rSize )
     789             : {
     790           0 :     uno::Reference< beans::XFastPropertySet > xFastPropertySet( xBitmapCanvas, uno::UNO_QUERY );
     791           0 :     if( xFastPropertySet.get() )
     792             :     {
     793             :         // 0 means get BitmapEx
     794           0 :         uno::Any aAny = xFastPropertySet->getFastPropertyValue( 0 );
     795           0 :         BitmapEx* pBitmapEx = (BitmapEx*) *reinterpret_cast<const sal_Int64*>(aAny.getValue());
     796           0 :         if( pBitmapEx )
     797             :         {
     798           0 :             *this = *pBitmapEx;
     799           0 :             delete pBitmapEx;
     800           0 :             return true;
     801           0 :         }
     802             :     }
     803             : 
     804             :     SalBitmap* pSalBmp, *pSalMask;
     805             : 
     806           0 :     pSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap();
     807           0 :     pSalMask = ImplGetSVData()->mpDefInst->CreateSalBitmap();
     808             : 
     809           0 :     Size aLocalSize(rSize);
     810           0 :     if( pSalBmp->Create( xBitmapCanvas, aLocalSize ) )
     811             :     {
     812           0 :         if ( pSalMask->Create( xBitmapCanvas, aLocalSize, true ) )
     813             :         {
     814           0 :             *this = BitmapEx(Bitmap(pSalBmp), Bitmap(pSalMask) );
     815           0 :             return true;
     816             :         }
     817             :         else
     818             :         {
     819           0 :             *this = BitmapEx(Bitmap(pSalBmp));
     820           0 :             return true;
     821             :         }
     822             :     }
     823             : 
     824           0 :     delete pSalBmp;
     825           0 :     delete pSalMask;
     826             : 
     827           0 :     return false;
     828             : }
     829             : 
     830             : // ------------------------------------------------------------------
     831             : 
     832             : namespace
     833             : {
     834     1491472 :     void impSmoothPoint(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
     835             :     {
     836     1491472 :         double fDeltaX(rSource.getX() - nIntX);
     837     1491472 :         double fDeltaY(rSource.getY() - nIntY);
     838     1491472 :         sal_Int32 nIndX(0L);
     839     1491472 :         sal_Int32 nIndY(0L);
     840             : 
     841     1491472 :         if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
     842             :         {
     843      734604 :             nIndX++;
     844             :         }
     845      756868 :         else if(fDeltaX < 0.0 && nIntX >= 1L)
     846             :         {
     847      745824 :             fDeltaX = -fDeltaX;
     848      745824 :             nIndX--;
     849             :         }
     850             : 
     851     1491472 :         if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
     852             :         {
     853      742444 :             nIndY++;
     854             :         }
     855      749028 :         else if(fDeltaY < 0.0 && nIntY >= 1L)
     856             :         {
     857      740132 :             fDeltaY = -fDeltaY;
     858      740132 :             nIndY--;
     859             :         }
     860             : 
     861     1491472 :         if(nIndX || nIndY)
     862             :         {
     863     1491460 :             const double fColorToReal(1.0 / 255.0);
     864     1491460 :             double fR(rValue.GetRed() * fColorToReal);
     865     1491460 :             double fG(rValue.GetGreen() * fColorToReal);
     866     1491460 :             double fB(rValue.GetBlue() * fColorToReal);
     867     1491460 :             double fRBottom(0.0), fGBottom(0.0), fBBottom(0.0);
     868             : 
     869     1491460 :             if(nIndX)
     870             :             {
     871     1480428 :                 const double fMulA(fDeltaX * fColorToReal);
     872     1480428 :                 double fMulB(1.0 - fDeltaX);
     873     1480428 :                 const BitmapColor aTopPartner(rRead.GetColor(nIntY, nIntX + nIndX));
     874             : 
     875     1480428 :                 fR = (fR * fMulB) + (aTopPartner.GetRed() * fMulA);
     876     1480428 :                 fG = (fG * fMulB) + (aTopPartner.GetGreen() * fMulA);
     877     1480428 :                 fB = (fB * fMulB) + (aTopPartner.GetBlue() * fMulA);
     878             : 
     879     1480428 :                 if(nIndY)
     880             :                 {
     881     1471544 :                     fMulB *= fColorToReal;
     882     1471544 :                     const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
     883     2943088 :                     const BitmapColor aBottomPartner(rRead.GetColor(nIntY + nIndY, nIntX + nIndX));
     884             : 
     885     1471544 :                     fRBottom = (aBottom.GetRed() * fMulB) + (aBottomPartner.GetRed() * fMulA);
     886     1471544 :                     fGBottom = (aBottom.GetGreen() * fMulB) + (aBottomPartner.GetGreen() * fMulA);
     887     2943088 :                     fBBottom = (aBottom.GetBlue() * fMulB) + (aBottomPartner.GetBlue() * fMulA);
     888     1480428 :                 }
     889             :             }
     890             : 
     891     1491460 :             if(nIndY)
     892             :             {
     893     1482576 :                 if(!nIndX)
     894             :                 {
     895       11032 :                     const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
     896             : 
     897       11032 :                     fRBottom = aBottom.GetRed() * fColorToReal;
     898       11032 :                     fGBottom = aBottom.GetGreen() * fColorToReal;
     899       11032 :                     fBBottom = aBottom.GetBlue() * fColorToReal;
     900             :                 }
     901             : 
     902     1482576 :                 const double fMulB(1.0 - fDeltaY);
     903             : 
     904     1482576 :                 fR = (fR * fMulB) + (fRBottom * fDeltaY);
     905     1482576 :                 fG = (fG * fMulB) + (fGBottom * fDeltaY);
     906     1482576 :                 fB = (fB * fMulB) + (fBBottom * fDeltaY);
     907             :             }
     908             : 
     909     1491460 :             rValue.SetRed((sal_uInt8)(fR * 255.0));
     910     1491460 :             rValue.SetGreen((sal_uInt8)(fG * 255.0));
     911     1491460 :             rValue.SetBlue((sal_uInt8)(fB * 255.0));
     912             :         }
     913     1491472 :     }
     914             : 
     915          68 :     Bitmap impTransformBitmap(
     916             :         const Bitmap& rSource,
     917             :         const Size aDestinationSize,
     918             :         const basegfx::B2DHomMatrix& rTransform,
     919             :         bool bSmooth)
     920             :     {
     921          68 :         Bitmap aDestination(aDestinationSize, 24);
     922          68 :         BitmapWriteAccess* pWrite = aDestination.AcquireWriteAccess();
     923             : 
     924          68 :         if(pWrite)
     925             :         {
     926          68 :             const Size aContentSizePixel(rSource.GetSizePixel());
     927          68 :             BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
     928             : 
     929          68 :             if(pRead)
     930             :             {
     931          68 :                 const Size aDestinationSizePixel(aDestination.GetSizePixel());
     932          68 :                 bool bWorkWithIndex(rSource.GetBitCount() <= 8);
     933          68 :                 BitmapColor aOutside(BitmapColor(0xff, 0xff, 0xff));
     934             : 
     935        9944 :                 for(sal_Int32 y(0L); y < aDestinationSizePixel.getHeight(); y++)
     936             :                 {
     937     1534076 :                     for(sal_Int32 x(0L); x < aDestinationSizePixel.getWidth(); x++)
     938             :                     {
     939     1524200 :                         const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
     940     1524200 :                         const sal_Int32 nIntX(basegfx::fround(aSourceCoor.getX()));
     941             : 
     942     1524200 :                         if(nIntX >= 0L && nIntX < aContentSizePixel.getWidth())
     943             :                         {
     944     1505088 :                             const sal_Int32 nIntY(basegfx::fround(aSourceCoor.getY()));
     945             : 
     946     1505088 :                             if(nIntY >= 0L && nIntY < aContentSizePixel.getHeight())
     947             :                             {
     948             :                                 // inside pixel
     949     1491472 :                                 BitmapColor aValue;
     950             : 
     951     1491472 :                                 if(bWorkWithIndex)
     952             :                                 {
     953      745736 :                                     aValue = pRead->GetPaletteColor(pRead->GetPixelIndex(nIntY, nIntX));
     954             :                                 }
     955             :                                 else
     956             :                                 {
     957      745736 :                                     aValue = pRead->GetPixel(nIntY, nIntX);
     958             :                                 }
     959             : 
     960     1491472 :                                 if(bSmooth)
     961             :                                 {
     962     1491472 :                                     impSmoothPoint(aValue, aSourceCoor, nIntX, nIntY, *pRead);
     963             :                                 }
     964             : 
     965     1491472 :                                 pWrite->SetPixel(y, x, aValue);
     966     1491472 :                                 continue;
     967             :                             }
     968             :                         }
     969             : 
     970             :                         // here are outside pixels. Complete mask
     971       32728 :                         if(bWorkWithIndex)
     972             :                         {
     973       16364 :                             pWrite->SetPixel(y, x, aOutside);
     974             :                         }
     975       32728 :                     }
     976             :                 }
     977             : 
     978          68 :                 delete pRead;
     979             :             }
     980             : 
     981          68 :             delete pWrite;
     982             :         }
     983             : 
     984          68 :         rSource.AdaptBitCount(aDestination);
     985             : 
     986          68 :         return aDestination;
     987             :     }
     988             : } // end of anonymous namespace
     989          34 : BitmapEx BitmapEx::TransformBitmapEx(
     990             :     double fWidth,
     991             :     double fHeight,
     992             :     const basegfx::B2DHomMatrix& rTransformation) const
     993             : {
     994          34 :     if(fWidth <= 1 || fHeight <= 1)
     995           0 :         return BitmapEx();
     996             : 
     997             :     // force destination to 24 bit, we want to smooth output
     998          34 :     const Size aDestinationSize(basegfx::fround(fWidth), basegfx::fround(fHeight));
     999             :     static bool bDoSmoothAtAll(true);
    1000          34 :     const Bitmap aDestination(impTransformBitmap(GetBitmap(), aDestinationSize, rTransformation, bDoSmoothAtAll));
    1001             : 
    1002             :     // create mask
    1003          34 :     if(IsTransparent())
    1004             :     {
    1005          34 :         if(IsAlpha())
    1006             :         {
    1007          34 :             const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, bDoSmoothAtAll));
    1008          34 :             return BitmapEx(aDestination, AlphaMask(aAlpha));
    1009             :         }
    1010             :         else
    1011             :         {
    1012           0 :             const Bitmap aLclMask(impTransformBitmap(GetMask(), aDestinationSize, rTransformation, false));
    1013           0 :             return BitmapEx(aDestination, aLclMask);
    1014             :         }
    1015             :     }
    1016             : 
    1017           0 :     return BitmapEx(aDestination);
    1018             : }
    1019             : 
    1020             : // ------------------------------------------------------------------
    1021             : 
    1022          34 : BitmapEx BitmapEx::getTransformed(
    1023             :     const basegfx::B2DHomMatrix& rTransformation,
    1024             :     double fMaximumArea) const
    1025             : {
    1026          34 :     BitmapEx aRetval;
    1027             : 
    1028          34 :     if(IsEmpty())
    1029           0 :         return aRetval;
    1030             : 
    1031          34 :     const sal_uInt32 nSourceWidth(GetSizePixel().Width());
    1032          34 :     const sal_uInt32 nSourceHeight(GetSizePixel().Height());
    1033             : 
    1034          34 :     if(!nSourceWidth || !nSourceHeight)
    1035           0 :         return aRetval;
    1036             : 
    1037             :     // Get dest range
    1038          34 :     basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
    1039          34 :     aOutlineRange.transform(rTransformation);
    1040             : 
    1041             :     // get target size
    1042          34 :     double fWidth(aOutlineRange.getWidth());
    1043          34 :     double fHeight(aOutlineRange.getHeight());
    1044             : 
    1045          34 :     if(fWidth < 1.0 || fHeight < 1.0)
    1046           0 :         return aRetval;
    1047             : 
    1048             :     // test if discrete size (pixel) maybe too big and limit it
    1049          34 :     const double fArea(fWidth * fHeight);
    1050          34 :     const bool bNeedToReduce(fArea > fMaximumArea);
    1051          34 :     double fReduceFactor(1.0);
    1052             : 
    1053          34 :     if(bNeedToReduce)
    1054             :     {
    1055           0 :         fReduceFactor = sqrt(fMaximumArea / fArea);
    1056           0 :         fWidth *= fReduceFactor;
    1057           0 :         fHeight *= fReduceFactor;
    1058             :     }
    1059             : 
    1060             :     // Build complete transform from source pixels to target pixels.
    1061             :     // Start by scaling from source pixel size to unit coordinates
    1062             :     basegfx::B2DHomMatrix aTransform(
    1063             :         basegfx::tools::createScaleB2DHomMatrix(
    1064             :             1.0 / nSourceWidth,
    1065          68 :             1.0 / nSourceHeight));
    1066             : 
    1067             :     // multiply with given transform which leads from unit coordinates inside
    1068             :     // aOutlineRange
    1069          34 :     aTransform = rTransformation * aTransform;
    1070             : 
    1071             :     // substract top-left of aOutlineRange
    1072          34 :     aTransform.translate(-aOutlineRange.getMinX(), -aOutlineRange.getMinY());
    1073             : 
    1074             :     // scale to target pixels (if needed)
    1075          34 :     if(bNeedToReduce)
    1076             :     {
    1077           0 :         aTransform.scale(fReduceFactor, fReduceFactor);
    1078             :     }
    1079             : 
    1080             :     // invert to get transformation from target pixel coordiates to source pixels
    1081          34 :     aTransform.invert();
    1082             : 
    1083             :     // create bitmap using source, destination and linear back-transformation
    1084          34 :     aRetval = TransformBitmapEx(fWidth, fHeight, aTransform);
    1085             : 
    1086          34 :     return aRetval;
    1087             : }
    1088             : 
    1089             : // ------------------------------------------------------------------
    1090             : 
    1091         204 : BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorModifierStack) const
    1092             : {
    1093         204 :     Bitmap aChangedBitmap(GetBitmap());
    1094         204 :     bool bDone(false);
    1095             : 
    1096         612 :     for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
    1097             :     {
    1098         204 :         const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
    1099             : 
    1100         204 :         switch(rModifier.getMode())
    1101             :         {
    1102             :             case basegfx::BCOLORMODIFYMODE_REPLACE :
    1103             :             {
    1104             :                 // complete replace
    1105         190 :                 if(IsTransparent())
    1106             :                 {
    1107             :                     // clear bitmap with dest color
    1108         190 :                     if(aChangedBitmap.GetBitCount() <= 8)
    1109             :                     {
    1110             :                         // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
    1111             :                         // erase color is determined and used -> this may be different from what is
    1112             :                         // wanted here. Better create a new bitmap with the needed color explicitely
    1113           0 :                         BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
    1114             :                         OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
    1115             : 
    1116           0 :                         if(pReadAccess)
    1117             :                         {
    1118           0 :                             BitmapPalette aNewPalette(pReadAccess->GetPalette());
    1119           0 :                             aNewPalette[0] = BitmapColor(Color(rModifier.getBColor()));
    1120           0 :                             aChangedBitmap = Bitmap(
    1121             :                                 aChangedBitmap.GetSizePixel(),
    1122           0 :                                 aChangedBitmap.GetBitCount(),
    1123           0 :                                 &aNewPalette);
    1124           0 :                             delete pReadAccess;
    1125             :                         }
    1126             :                     }
    1127             :                     else
    1128             :                     {
    1129         190 :                         aChangedBitmap.Erase(Color(rModifier.getBColor()));
    1130             :                     }
    1131             :                 }
    1132             :                 else
    1133             :                 {
    1134             :                     // erase bitmap, caller will know to paint direct
    1135           0 :                     aChangedBitmap.SetEmpty();
    1136             :                 }
    1137             : 
    1138         190 :                 bDone = true;
    1139         190 :                 break;
    1140             :             }
    1141             : 
    1142             :             default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
    1143             :             {
    1144          14 :                 BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
    1145             : 
    1146          14 :                 if(pContent)
    1147             :                 {
    1148          14 :                     const double fConvertColor(1.0 / 255.0);
    1149             : 
    1150        1408 :                     for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
    1151             :                     {
    1152      185690 :                         for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
    1153             :                         {
    1154      184296 :                             const BitmapColor aBMCol(pContent->GetColor(y, x));
    1155             :                             const basegfx::BColor aBSource(
    1156      184296 :                                 (double)aBMCol.GetRed() * fConvertColor,
    1157      184296 :                                 (double)aBMCol.GetGreen() * fConvertColor,
    1158      737184 :                                 (double)aBMCol.GetBlue() * fConvertColor);
    1159      368592 :                             const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource));
    1160             : 
    1161      184296 :                             pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
    1162      184296 :                         }
    1163             :                     }
    1164             : 
    1165          14 :                     delete pContent;
    1166             :                 }
    1167             : 
    1168          14 :                 break;
    1169             :             }
    1170             :         }
    1171             :     }
    1172             : 
    1173         204 :     if(aChangedBitmap.IsEmpty())
    1174             :     {
    1175           0 :         return BitmapEx();
    1176             :     }
    1177             :     else
    1178             :     {
    1179         204 :         if(IsTransparent())
    1180             :         {
    1181         190 :             if(IsAlpha())
    1182             :             {
    1183         190 :                 return BitmapEx(aChangedBitmap, GetAlpha());
    1184             :             }
    1185             :             else
    1186             :             {
    1187           0 :                 return BitmapEx(aChangedBitmap, GetMask());
    1188             :             }
    1189             :         }
    1190             :         else
    1191             :         {
    1192          14 :             return BitmapEx(aChangedBitmap);
    1193             :         }
    1194         204 :     }
    1195             : }
    1196             : 
    1197             : // -----------------------------------------------------------------------------
    1198             : 
    1199         130 : BitmapEx VCL_DLLPUBLIC createBlendFrame(
    1200             :     const Size& rSize,
    1201             :     sal_uInt8 nAlpha,
    1202             :     Color aColorTopLeft,
    1203             :     Color aColorBottomRight)
    1204             : {
    1205         130 :     const sal_uInt32 nW(rSize.Width());
    1206         130 :     const sal_uInt32 nH(rSize.Height());
    1207             : 
    1208         130 :     if(nW || nH)
    1209             :     {
    1210         130 :         Color aColTopRight(aColorTopLeft);
    1211         130 :         Color aColBottomLeft(aColorTopLeft);
    1212         130 :         const sal_uInt32 nDE(nW + nH);
    1213             : 
    1214         130 :         aColTopRight.Merge(aColorBottomRight, 255 - sal_uInt8((nW * 255) / nDE));
    1215         130 :         aColBottomLeft.Merge(aColorBottomRight, 255 - sal_uInt8((nH * 255) / nDE));
    1216             : 
    1217         130 :         return createBlendFrame(rSize, nAlpha, aColorTopLeft, aColTopRight, aColorBottomRight, aColBottomLeft);
    1218             :     }
    1219             : 
    1220           0 :     return BitmapEx();
    1221             : }
    1222             : 
    1223         130 : BitmapEx VCL_DLLPUBLIC createBlendFrame(
    1224             :     const Size& rSize,
    1225             :     sal_uInt8 nAlpha,
    1226             :     Color aColorTopLeft,
    1227             :     Color aColorTopRight,
    1228             :     Color aColorBottomRight,
    1229             :     Color aColorBottomLeft)
    1230             : {
    1231         130 :     BlendFrameCache* pBlendFrameCache = ImplGetBlendFrameCache();
    1232             : 
    1233         260 :     if(pBlendFrameCache->m_aLastSize == rSize
    1234         123 :         && pBlendFrameCache->m_nLastAlpha == nAlpha
    1235         123 :         && pBlendFrameCache->m_aLastColorTopLeft == aColorTopLeft
    1236         123 :         && pBlendFrameCache->m_aLastColorTopRight == aColorTopRight
    1237         123 :         && pBlendFrameCache->m_aLastColorBottomRight == aColorBottomRight
    1238         253 :         && pBlendFrameCache->m_aLastColorBottomLeft == aColorBottomLeft)
    1239             :     {
    1240         123 :         return pBlendFrameCache->m_aLastResult;
    1241             :     }
    1242             : 
    1243           7 :     pBlendFrameCache->m_aLastSize = rSize;
    1244           7 :     pBlendFrameCache->m_nLastAlpha = nAlpha;
    1245           7 :     pBlendFrameCache->m_aLastColorTopLeft = aColorTopLeft;
    1246           7 :     pBlendFrameCache->m_aLastColorTopRight = aColorTopRight;
    1247           7 :     pBlendFrameCache->m_aLastColorBottomRight = aColorBottomRight;
    1248           7 :     pBlendFrameCache->m_aLastColorBottomLeft = aColorBottomLeft;
    1249           7 :     pBlendFrameCache->m_aLastResult.Clear();
    1250             : 
    1251           7 :     const long nW(rSize.Width());
    1252           7 :     const long nH(rSize.Height());
    1253             : 
    1254           7 :     if(nW && nH)
    1255             :     {
    1256           7 :         sal_uInt8 aEraseTrans(0xff);
    1257           7 :         Bitmap aContent(rSize, 24);
    1258          14 :         AlphaMask aAlpha(rSize, &aEraseTrans);
    1259             : 
    1260           7 :         aContent.Erase(COL_BLACK);
    1261             : 
    1262           7 :         BitmapWriteAccess* pContent = aContent.AcquireWriteAccess();
    1263           7 :         BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess();
    1264             : 
    1265           7 :         if(pContent && pAlpha)
    1266             :         {
    1267           7 :             long x(0);
    1268           7 :             long y(0);
    1269             : 
    1270             :             // x == 0, y == 0
    1271           7 :             pContent->SetPixel(y, x, aColorTopLeft);
    1272           7 :             pAlpha->SetPixelIndex(y, x, nAlpha);
    1273             : 
    1274         210 :             for(x = 1; x < nW - 1; x++) // y == 0
    1275             :             {
    1276         203 :                 Color aMix(aColorTopLeft);
    1277             : 
    1278         203 :                 aMix.Merge(aColorTopRight, 255 - sal_uInt8((x * 255) / nW));
    1279         203 :                 pContent->SetPixel(y, x, aMix);
    1280         203 :                 pAlpha->SetPixelIndex(y, x, nAlpha);
    1281             :             }
    1282             : 
    1283             :             // x == nW - 1, y == 0
    1284           7 :             pContent->SetPixel(y, x, aColorTopRight);
    1285           7 :             pAlpha->SetPixelIndex(y, x, nAlpha);
    1286             : 
    1287          70 :             for(y = 1; y < nH - 1; y++) // x == 0 and nW - 1
    1288             :             {
    1289          63 :                 Color aMixA(aColorTopLeft);
    1290          63 :                 Color aMixB(aColorTopRight);
    1291             : 
    1292          63 :                 aMixA.Merge(aColorBottomLeft, 255 - sal_uInt8((y * 255) / nH));
    1293          63 :                 pContent->SetPixel(y, 0, aMixA);
    1294          63 :                 pAlpha->SetPixelIndex(y, 0, nAlpha);
    1295             : 
    1296          63 :                 aMixB.Merge(aColorBottomRight, 255 - sal_uInt8((y * 255) / nH));
    1297          63 :                 pContent->SetPixel(y, nW - 1, aMixB);
    1298          63 :                 pAlpha->SetPixelIndex(y, nW - 1, nAlpha);
    1299             :             }
    1300             : 
    1301           7 :             x = 0; // x == 0, y == nH - 1
    1302           7 :             pContent->SetPixel(y, x, aColorBottomLeft);
    1303           7 :             pAlpha->SetPixelIndex(y, x, nAlpha);
    1304             : 
    1305         210 :             for(x = 1; x < nW - 1; x++) // y == nH - 1
    1306             :             {
    1307         203 :                 Color aMix(aColorBottomLeft);
    1308             : 
    1309         203 :                 aMix.Merge(aColorBottomRight, 255 - sal_uInt8(((x - 0)* 255) / nW));
    1310         203 :                 pContent->SetPixel(y, x, aMix);
    1311         203 :                 pAlpha->SetPixelIndex(y, x, nAlpha);
    1312             :             }
    1313             : 
    1314             :             // x == nW - 1, y == nH - 1
    1315           7 :             pContent->SetPixel(y, x, aColorBottomRight);
    1316           7 :             pAlpha->SetPixelIndex(y, x, nAlpha);
    1317             : 
    1318           7 :             aContent.ReleaseAccess(pContent);
    1319           7 :             aAlpha.ReleaseAccess(pAlpha);
    1320             : 
    1321           7 :             pBlendFrameCache->m_aLastResult = BitmapEx(aContent, aAlpha);
    1322             :         }
    1323             :         else
    1324             :         {
    1325           0 :             if(pContent)
    1326             :             {
    1327           0 :                 aContent.ReleaseAccess(pContent);
    1328             :             }
    1329             : 
    1330           0 :             if(pAlpha)
    1331             :             {
    1332           0 :                 aAlpha.ReleaseAccess(pAlpha);
    1333             :             }
    1334           7 :         }
    1335             :     }
    1336             : 
    1337           7 :     return pBlendFrameCache->m_aLastResult;
    1338         465 : }
    1339             : 
    1340             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10