[Libreoffice-commits] core.git: vcl/Library_vcl.mk vcl/source

Chris Sherlock chris.sherlock79 at gmail.com
Tue Mar 6 04:08:42 UTC 2018


 vcl/Library_vcl.mk                |    3 
 vcl/source/bitmap/bitmap.cxx      | 1088 -----------------------------------
 vcl/source/bitmap/bitmappaint.cxx | 1158 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 1164 insertions(+), 1085 deletions(-)

New commits:
commit bdd62b4c327ab894dbba00fe2e07696c1b7d9de6
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Thu Mar 1 06:07:39 2018 +1100

    vcl: split painting bitmap functions to bitmappaint.cxx
    
    Change-Id: Ib5f52e4b7b5121de15cdb205165fcbdb8b09bc8a
    Reviewed-on: https://gerrit.libreoffice.org/50530
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index b116fd15705a..9e292916f843 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -300,8 +300,9 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/gdi/wall \
     vcl/source/gdi/scrptrun \
     vcl/source/gdi/CommonSalLayout \
-    vcl/source/bitmap/bitmap \
+	vcl/source/bitmap/bitmap \
     vcl/source/bitmap/bitmapfilter \
+    vcl/source/bitmap/bitmappaint \
     vcl/source/bitmap/bitmapscalesuper \
     vcl/source/bitmap/BitmapScaleConvolution \
     vcl/source/bitmap/BitmapSymmetryCheck \
diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx
index bf670f20ffce..b5602327f75d 100644
--- a/vcl/source/bitmap/bitmap.cxx
+++ b/vcl/source/bitmap/bitmap.cxx
@@ -17,20 +17,15 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include <algorithm>
-#include <rtl/crc.h>
-#include <tools/stream.hxx>
-#include <tools/poly.hxx>
-#include <vcl/salbtype.hxx>
+#include <osl/diagnose.h>
+#include <vcl/bitmap.hxx>
 #include <vcl/bitmapaccess.hxx>
 #include <vcl/outdev.hxx>
-#include <vcl/bitmap.hxx>
-#include <vcl/bitmapex.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/image.hxx>
 
 #include <impbmp.hxx>
 #include <salbmp.hxx>
+
+#include <algorithm>
 #include <memory>
 
 Bitmap::Bitmap()
@@ -377,366 +372,6 @@ void Bitmap::ReleaseAccess( BitmapInfoAccess* pBitmapAccess )
     delete pBitmapAccess;
 }
 
-bool Bitmap::Erase(const Color& rFillColor)
-{
-    if (IsEmpty())
-        return true;
-
-    Bitmap::ScopedWriteAccess  pWriteAcc(*this);
-    bool bRet = false;
-
-    if (pWriteAcc)
-    {
-        const ScanlineFormat nFormat = pWriteAcc->GetScanlineFormat();
-        sal_uInt8 cIndex = 0;
-        bool bFast = false;
-
-        switch (nFormat)
-        {
-            case ScanlineFormat::N1BitMsbPal:
-            case ScanlineFormat::N1BitLsbPal:
-            {
-                cIndex = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex(rFillColor));
-                cIndex = (cIndex ? 255 : 0);
-                bFast = true;
-            }
-            break;
-
-            case ScanlineFormat::N4BitMsnPal:
-            case ScanlineFormat::N4BitLsnPal:
-            {
-                cIndex = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex(rFillColor));
-                cIndex = cIndex | ( cIndex << 4 );
-                bFast = true;
-            }
-            break;
-
-            case ScanlineFormat::N8BitPal:
-            {
-                cIndex = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex(rFillColor));
-                bFast = true;
-            }
-            break;
-
-            case ScanlineFormat::N24BitTcBgr:
-            case ScanlineFormat::N24BitTcRgb:
-            {
-                if (rFillColor.GetRed() == rFillColor.GetGreen() &&
-                    rFillColor.GetRed() == rFillColor.GetBlue())
-                {
-                    cIndex = rFillColor.GetRed();
-                    bFast = true;
-                }
-                else
-                    bFast = false;
-            }
-            break;
-
-            default:
-                bFast = false;
-            break;
-        }
-
-        if( bFast )
-        {
-            const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
-            memset( pWriteAcc->GetBuffer(), cIndex, nBufSize );
-        }
-        else
-        {
-            const tools::Rectangle aRect( Point(), Size( pWriteAcc->Width(), pWriteAcc->Height() ) );
-            pWriteAcc->SetFillColor( rFillColor );
-            pWriteAcc->FillRect( aRect );
-        }
-
-        bRet = true;
-    }
-
-    return bRet;
-}
-
-bool Bitmap::Invert()
-{
-    ScopedWriteAccess   pAcc(*this);
-    bool                bRet = false;
-
-    if( pAcc )
-    {
-        if( pAcc->HasPalette() )
-        {
-            BitmapPalette   aBmpPal( pAcc->GetPalette() );
-            const sal_uInt16    nCount = aBmpPal.GetEntryCount();
-
-            for( sal_uInt16 i = 0; i < nCount; i++ )
-                aBmpPal[ i ].Invert();
-
-            pAcc->SetPalette( aBmpPal );
-        }
-        else
-        {
-            const long  nWidth = pAcc->Width();
-            const long  nHeight = pAcc->Height();
-
-            for( long nY = 0; nY < nHeight; nY++ )
-            {
-                Scanline pScanline = pAcc->GetScanline(nY);
-                for( long nX = 0; nX < nWidth; nX++ )
-                    pAcc->SetPixelOnData( pScanline, nX, pAcc->GetPixelFromData( pScanline, nX ).Invert() );
-            }
-        }
-
-        mxImpBmp->ImplInvalidateChecksum();
-        pAcc.reset();
-        bRet = true;
-    }
-
-    return bRet;
-}
-
-bool Bitmap::Mirror( BmpMirrorFlags nMirrorFlags )
-{
-    bool bHorz( nMirrorFlags & BmpMirrorFlags::Horizontal );
-    bool bVert( nMirrorFlags & BmpMirrorFlags::Vertical );
-    bool bRet = false;
-
-    if( bHorz && !bVert )
-    {
-        ScopedWriteAccess   pAcc(*this);
-
-        if( pAcc )
-        {
-            const long  nWidth = pAcc->Width();
-            const long  nHeight = pAcc->Height();
-            const long  nWidth1 = nWidth - 1;
-            const long  nWidth_2 = nWidth >> 1;
-
-            for( long nY = 0; nY < nHeight; nY++ )
-            {
-                Scanline pScanline = pAcc->GetScanline(nY);
-                for( long nX = 0, nOther = nWidth1; nX < nWidth_2; nX++, nOther-- )
-                {
-                    const BitmapColor aTemp( pAcc->GetPixelFromData( pScanline, nX ) );
-
-                    pAcc->SetPixelOnData( pScanline, nX, pAcc->GetPixelFromData( pScanline, nOther ) );
-                    pAcc->SetPixelOnData( pScanline, nOther, aTemp );
-                }
-            }
-
-            pAcc.reset();
-            bRet = true;
-        }
-    }
-    else if( bVert && !bHorz )
-    {
-        ScopedWriteAccess   pAcc(*this);
-
-        if( pAcc )
-        {
-            const long  nScanSize = pAcc->GetScanlineSize();
-            std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[ nScanSize ]);
-            const long  nHeight = pAcc->Height();
-            const long  nHeight1 = nHeight - 1;
-            const long  nHeight_2 = nHeight >> 1;
-
-            for( long nY = 0, nOther = nHeight1; nY < nHeight_2; nY++, nOther-- )
-            {
-                memcpy( pBuffer.get(), pAcc->GetScanline( nY ), nScanSize );
-                memcpy( pAcc->GetScanline( nY ), pAcc->GetScanline( nOther ), nScanSize );
-                memcpy( pAcc->GetScanline( nOther ), pBuffer.get(), nScanSize );
-            }
-
-            pAcc.reset();
-            bRet = true;
-        }
-    }
-    else if( bHorz && bVert )
-    {
-        ScopedWriteAccess   pAcc(*this);
-
-        if( pAcc )
-        {
-            const long  nWidth = pAcc->Width();
-            const long  nWidth1 = nWidth - 1;
-            const long  nHeight = pAcc->Height();
-            long        nHeight_2 = nHeight >> 1;
-
-            for( long nY = 0, nOtherY = nHeight - 1; nY < nHeight_2; nY++, nOtherY-- )
-            {
-                Scanline pScanline = pAcc->GetScanline(nY);
-                Scanline pScanlineOther = pAcc->GetScanline(nOtherY);
-                for( long nX = 0, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX-- )
-                {
-                    const BitmapColor aTemp( pAcc->GetPixelFromData( pScanline, nX ) );
-
-                    pAcc->SetPixelOnData( pScanline, nX, pAcc->GetPixelFromData( pScanlineOther, nOtherX ) );
-                    pAcc->SetPixelOnData( pScanlineOther, nOtherX, aTemp );
-                }
-            }
-
-            // if necessary, also mirror the middle line horizontally
-            if( nHeight & 1 )
-            {
-                Scanline pScanline = pAcc->GetScanline(nHeight_2);
-                for( long nX = 0, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2; nX++, nOtherX-- )
-                {
-                    const BitmapColor aTemp( pAcc->GetPixelFromData( pScanline, nX ) );
-                    pAcc->SetPixelOnData( pScanline, nX, pAcc->GetPixelFromData( pScanline, nOtherX ) );
-                    pAcc->SetPixelOnData( pScanline, nOtherX, aTemp );
-                }
-            }
-
-            pAcc.reset();
-            bRet = true;
-        }
-    }
-    else
-        bRet = true;
-
-    return bRet;
-}
-
-bool Bitmap::Rotate( long nAngle10, const Color& rFillColor )
-{
-    bool bRet = false;
-
-    nAngle10 %= 3600;
-    nAngle10 = ( nAngle10 < 0 ) ? ( 3599L + nAngle10 ) : nAngle10;
-
-    if( !nAngle10    )
-        bRet = true;
-    else if( 1800 == nAngle10 )
-        bRet = Mirror( BmpMirrorFlags::Horizontal | BmpMirrorFlags::Vertical );
-    else
-    {
-        ScopedReadAccess    pReadAcc(*this);
-        Bitmap              aRotatedBmp;
-
-        if( pReadAcc )
-        {
-            const Size  aSizePix( GetSizePixel() );
-
-            if( ( 900 == nAngle10 ) || ( 2700 == nAngle10 ) )
-            {
-                const Size          aNewSizePix( aSizePix.Height(), aSizePix.Width() );
-                Bitmap              aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
-                ScopedWriteAccess   pWriteAcc(aNewBmp);
-
-                if( pWriteAcc )
-                {
-                    const long  nWidth = aSizePix.Width();
-                    const long  nWidth1 = nWidth - 1;
-                    const long  nHeight = aSizePix.Height();
-                    const long  nHeight1 = nHeight - 1;
-                    const long  nNewWidth = aNewSizePix.Width();
-                    const long  nNewHeight = aNewSizePix.Height();
-
-                    if( 900 == nAngle10 )
-                    {
-                        for( long nY = 0, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX-- )
-                        {
-                            Scanline pScanline = pWriteAcc->GetScanline(nY);
-                            for( long nX = 0, nOtherY = 0; nX < nNewWidth; nX++ )
-                                pWriteAcc->SetPixelOnData( pScanline, nX, pReadAcc->GetPixel( nOtherY++, nOtherX ) );
-                        }
-                    }
-                    else if( 2700 == nAngle10 )
-                    {
-                        for( long nY = 0, nOtherX = 0; nY < nNewHeight; nY++, nOtherX++ )
-                        {
-                            Scanline pScanline = pWriteAcc->GetScanline(nY);
-                            for( long nX = 0, nOtherY = nHeight1; nX < nNewWidth; nX++ )
-                                pWriteAcc->SetPixelOnData( pScanline, nX, pReadAcc->GetPixel( nOtherY--, nOtherX ) );
-                        }
-                    }
-
-                    pWriteAcc.reset();
-                }
-
-                aRotatedBmp = aNewBmp;
-            }
-            else
-            {
-                Point       aTmpPoint;
-                tools::Rectangle   aTmpRectangle( aTmpPoint, aSizePix );
-                tools::Polygon aPoly( aTmpRectangle );
-                aPoly.Rotate( aTmpPoint, static_cast<sal_uInt16>(nAngle10) );
-
-                tools::Rectangle           aNewBound( aPoly.GetBoundRect() );
-                const Size          aNewSizePix( aNewBound.GetSize() );
-                Bitmap              aNewBmp( aNewSizePix, GetBitCount(), &pReadAcc->GetPalette() );
-                ScopedWriteAccess   pWriteAcc(aNewBmp);
-
-                if( pWriteAcc )
-                {
-                    const BitmapColor   aFillColor( pWriteAcc->GetBestMatchingColor( rFillColor ) );
-                    const double        fCosAngle = cos( nAngle10 * F_PI1800 );
-                    const double        fSinAngle = sin( nAngle10 * F_PI1800 );
-                    const double        fXMin = aNewBound.Left();
-                    const double        fYMin = aNewBound.Top();
-                    const long          nWidth = aSizePix.Width();
-                    const long          nHeight = aSizePix.Height();
-                    const long          nNewWidth = aNewSizePix.Width();
-                    const long          nNewHeight = aNewSizePix.Height();
-                    long                nX;
-                    long                nY;
-                    long                nRotX;
-                    long                nRotY;
-                    std::unique_ptr<long[]> pCosX(new long[ nNewWidth ]);
-                    std::unique_ptr<long[]> pSinX(new long[ nNewWidth ]);
-                    std::unique_ptr<long[]> pCosY(new long[ nNewHeight ]);
-                    std::unique_ptr<long[]> pSinY(new long[ nNewHeight ]);
-
-                    for ( nX = 0; nX < nNewWidth; nX++ )
-                    {
-                        const double fTmp = ( fXMin + nX ) * 64.;
-
-                        pCosX[ nX ] = FRound( fCosAngle * fTmp );
-                        pSinX[ nX ] = FRound( fSinAngle * fTmp );
-                    }
-
-                    for ( nY = 0; nY < nNewHeight; nY++ )
-                    {
-                        const double fTmp = ( fYMin + nY ) * 64.;
-
-                        pCosY[ nY ] = FRound( fCosAngle * fTmp );
-                        pSinY[ nY ] = FRound( fSinAngle * fTmp );
-                    }
-
-                    for( nY = 0; nY < nNewHeight; nY++ )
-                    {
-                        long nSinY = pSinY[ nY ];
-                        long nCosY = pCosY[ nY ];
-                        Scanline pScanline = pWriteAcc->GetScanline(nY);
-
-                        for( nX = 0; nX < nNewWidth; nX++ )
-                        {
-                            nRotX = ( pCosX[ nX ] - nSinY ) >> 6;
-                            nRotY = ( pSinX[ nX ] + nCosY ) >> 6;
-
-                            if ( ( nRotX > -1 ) && ( nRotX < nWidth ) && ( nRotY > -1 ) && ( nRotY < nHeight ) )
-                                pWriteAcc->SetPixelOnData( pScanline, nX, pReadAcc->GetPixel( nRotY, nRotX ) );
-                            else
-                                pWriteAcc->SetPixelOnData( pScanline, nX, aFillColor );
-                        }
-                    }
-
-                    pWriteAcc.reset();
-                }
-
-                aRotatedBmp = aNewBmp;
-            }
-
-            pReadAcc.reset();
-        }
-
-        bRet = !!aRotatedBmp;
-        if( bRet )
-            ImplAssignWithSize( aRotatedBmp );
-    }
-
-    return bRet;
-};
-
 bool Bitmap::Crop( const tools::Rectangle& rRectPixel )
 {
     const Size          aSizePix( GetSizePixel() );
@@ -1182,625 +817,6 @@ bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor )
     return bRet;
 }
 
-Bitmap Bitmap::CreateMask( const Color& rTransColor, sal_uInt8 nTol ) const
-{
-    ScopedReadAccess pReadAcc(const_cast<Bitmap&>(*this));
-
-    if (!nTol && pReadAcc && (pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitLsbPal || pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal)
-        && pReadAcc->GetBestMatchingColor(COL_WHITE) == pReadAcc->GetBestMatchingColor(rTransColor))
-    {
-        //if we're a 1 bit pixel already, and the transcolor matches the color that would replace it already, then just return a copy
-        return *this;
-    }
-
-    Bitmap              aNewBmp(GetSizePixel(), 1);
-    ScopedWriteAccess   pWriteAcc(aNewBmp);
-    bool                bRet = false;
-
-    if (pWriteAcc && pReadAcc)
-    {
-        const long          nWidth = pReadAcc->Width();
-        const long          nHeight = pReadAcc->Height();
-        const BitmapColor   aBlack( pWriteAcc->GetBestMatchingColor( COL_BLACK ) );
-        const BitmapColor   aWhite( pWriteAcc->GetBestMatchingColor( COL_WHITE ) );
-
-        if( !nTol )
-        {
-            const BitmapColor   aTest( pReadAcc->GetBestMatchingColor( rTransColor ) );
-
-            if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N4BitMsnPal ||
-                pReadAcc->GetScanlineFormat() == ScanlineFormat::N4BitLsnPal )
-            {
-                // optimized for 4Bit-MSN/LSN source palette
-                const sal_uInt8 cTest = aTest.GetIndex();
-                const long nShiftInit = ( ( pReadAcc->GetScanlineFormat() == ScanlineFormat::N4BitMsnPal ) ? 4 : 0 );
-
-                if( pWriteAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal &&
-                    aWhite.GetIndex() == 1 )
-                {
-                    // optimized for 1Bit-MSB destination palette
-                    for (long nY = 0; nY < nHeight; ++nY)
-                    {
-                        Scanline pSrc = pReadAcc->GetScanline( nY );
-                        Scanline pDst = pWriteAcc->GetScanline( nY );
-                        for (long nX = 0, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4)
-                        {
-                            if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
-                                pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
-                            else
-                                pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
-                        }
-                    }
-                }
-                else
-                {
-                    for (long nY = 0; nY < nHeight; ++nY)
-                    {
-                        Scanline pSrc = pReadAcc->GetScanline( nY );
-                        Scanline pDst = pWriteAcc->GetScanline( nY );
-                        for (long nX = 0, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4)
-                        {
-                            if( cTest == ( ( pSrc[ nX >> 1 ] >> nShift ) & 0x0f ) )
-                                pWriteAcc->SetPixelOnData( pDst, nX, aWhite );
-                            else
-                                pWriteAcc->SetPixelOnData( pDst, nX, aBlack );
-                        }
-                    }
-                }
-            }
-            else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N8BitPal )
-            {
-                // optimized for 8Bit source palette
-                const sal_uInt8 cTest = aTest.GetIndex();
-
-                if( pWriteAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal &&
-                    aWhite.GetIndex() == 1 )
-                {
-                    // optimized for 1Bit-MSB destination palette
-                    for (long nY = 0; nY < nHeight; ++nY)
-                    {
-                        Scanline pSrc = pReadAcc->GetScanline( nY );
-                        Scanline pDst = pWriteAcc->GetScanline( nY );
-                        for (long nX = 0; nX < nWidth; ++nX)
-                        {
-                            if( cTest == pSrc[ nX ] )
-                                pDst[ nX >> 3 ] |= 1 << ( 7 - ( nX & 7 ) );
-                            else
-                                pDst[ nX >> 3 ] &= ~( 1 << ( 7 - ( nX & 7 ) ) );
-                        }
-                    }
-                }
-                else
-                {
-                    for (long nY = 0; nY < nHeight; ++nY)
-                    {
-                        Scanline pSrc = pReadAcc->GetScanline( nY );
-                        Scanline pDst = pWriteAcc->GetScanline( nY );
-                        for (long nX = 0; nX < nWidth; ++nX)
-                        {
-                            if( cTest == pSrc[ nX ] )
-                                pWriteAcc->SetPixelOnData( pDst, nX, aWhite );
-                            else
-                                pWriteAcc->SetPixelOnData( pDst, nX, aBlack );
-                        }
-                    }
-                }
-            }
-            else if (pWriteAcc->GetScanlineFormat() == pReadAcc->GetScanlineFormat() && aWhite.GetIndex() == 1 &&
-                     (pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitLsbPal || pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal))
-            {
-                for (long nY = 0; nY < nHeight; ++nY)
-                {
-                    Scanline pSrc = pReadAcc->GetScanline(nY);
-                    Scanline pDst = pWriteAcc->GetScanline(nY);
-                    assert(pWriteAcc->GetScanlineSize() == pReadAcc->GetScanlineSize());
-                    const long nScanlineSize = pWriteAcc->GetScanlineSize();
-                    for (long nX = 0; nX < nScanlineSize; ++nX)
-                        pDst[nX] = ~pSrc[nX];
-                }
-            }
-            else
-            {
-                // not optimized
-                for (long nY = 0; nY < nHeight; ++nY)
-                {
-                    Scanline pScanline = pWriteAcc->GetScanline( nY );
-                    Scanline pScanlineRead = pReadAcc->GetScanline( nY );
-                    for (long nX = 0; nX < nWidth; ++nX)
-                    {
-                        if( aTest == pReadAcc->GetPixelFromData( pScanlineRead, nX ) )
-                            pWriteAcc->SetPixelOnData( pScanline, nX, aWhite );
-                        else
-                            pWriteAcc->SetPixelOnData( pScanline, nX, aBlack );
-                    }
-                }
-            }
-        }
-        else
-        {
-            BitmapColor aCol;
-            long        nR, nG, nB;
-            const long  nMinR = MinMax<long>(rTransColor.GetRed() - nTol, 0, 255);
-            const long  nMaxR = MinMax<long>(rTransColor.GetRed() + nTol, 0, 255);
-            const long  nMinG = MinMax<long>(rTransColor.GetGreen() - nTol, 0, 255);
-            const long  nMaxG = MinMax<long>(rTransColor.GetGreen() + nTol, 0, 255);
-            const long  nMinB = MinMax<long>(rTransColor.GetBlue() - nTol, 0, 255);
-            const long  nMaxB = MinMax<long>(rTransColor.GetBlue() + nTol, 0, 255);
-
-            if( pReadAcc->HasPalette() )
-            {
-                for( long nY = 0; nY < nHeight; nY++ )
-                {
-                    Scanline pScanline = pWriteAcc->GetScanline( nY );
-                    Scanline pScanlineRead = pReadAcc->GetScanline(nY);
-                    for( long nX = 0; nX < nWidth; nX++ )
-                    {
-                        aCol = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nX ) );
-                        nR = aCol.GetRed();
-                        nG = aCol.GetGreen();
-                        nB = aCol.GetBlue();
-
-                        if( nMinR <= nR && nMaxR >= nR &&
-                            nMinG <= nG && nMaxG >= nG &&
-                            nMinB <= nB && nMaxB >= nB )
-                        {
-                            pWriteAcc->SetPixelOnData( pScanline, nX, aWhite );
-                        }
-                        else
-                            pWriteAcc->SetPixelOnData( pScanline, nX, aBlack );
-                    }
-                }
-            }
-            else
-            {
-                for( long nY = 0; nY < nHeight; nY++ )
-                {
-                    Scanline pScanline = pWriteAcc->GetScanline( nY );
-                    Scanline pScanlineRead = pReadAcc->GetScanline(nY);
-                    for( long nX = 0; nX < nWidth; nX++ )
-                    {
-                        aCol = pReadAcc->GetPixelFromData( pScanlineRead, nX );
-                        nR = aCol.GetRed();
-                        nG = aCol.GetGreen();
-                        nB = aCol.GetBlue();
-
-                        if( nMinR <= nR && nMaxR >= nR &&
-                            nMinG <= nG && nMaxG >= nG &&
-                            nMinB <= nB && nMaxB >= nB )
-                        {
-                            pWriteAcc->SetPixelOnData( pScanline, nX, aWhite );
-                        }
-                        else
-                            pWriteAcc->SetPixelOnData( pScanline, nX, aBlack );
-                    }
-                }
-            }
-        }
-
-        bRet = true;
-    }
-
-    pWriteAcc.reset();
-    pReadAcc.reset();
-
-    if( bRet )
-    {
-        aNewBmp.maPrefSize = maPrefSize;
-        aNewBmp.maPrefMapMode = maPrefMapMode;
-    }
-    else
-        aNewBmp = Bitmap();
-
-    return aNewBmp;
-}
-
-vcl::Region Bitmap::CreateRegion( const Color& rColor, const tools::Rectangle& rRect ) const
-{
-    vcl::Region         aRegion;
-    tools::Rectangle           aRect( rRect );
-    ScopedReadAccess    pReadAcc(const_cast<Bitmap&>(*this));
-
-    aRect.Intersection( tools::Rectangle( Point(), GetSizePixel() ) );
-    aRect.Justify();
-
-    if( pReadAcc )
-    {
-        //Rectangle         aSubRect;
-        const long          nLeft = aRect.Left();
-        const long          nTop = aRect.Top();
-        const long          nRight = aRect.Right();
-        const long          nBottom = aRect.Bottom();
-        const BitmapColor   aMatch( pReadAcc->GetBestMatchingColor( rColor ) );
-
-        //RectangleVector aRectangles;
-        //aRegion.ImplBeginAddRect();
-        std::vector< long > aLine;
-        long nYStart(nTop);
-        long nY(nTop);
-
-        for( ; nY <= nBottom; nY++ )
-        {
-            //aSubRect.Top() = aSubRect.Bottom() = nY;
-            std::vector< long > aNewLine;
-            long nX(nLeft);
-            Scanline pScanlineRead = pReadAcc->GetScanline(nY);
-
-            for( ; nX <= nRight; )
-            {
-                while( ( nX <= nRight ) && ( aMatch != pReadAcc->GetPixelFromData( pScanlineRead, nX ) ) )
-                    nX++;
-
-                if( nX <= nRight )
-                {
-                    aNewLine.push_back(nX);
-                    //aSubRect.Left() = nX;
-
-                    while( ( nX <= nRight ) && ( aMatch == pReadAcc->GetPixelFromData( pScanlineRead, nX ) ) )
-                        nX++;
-
-                    //aSubRect.Right() = nX - 1;
-                    aNewLine.push_back(nX - 1);
-
-                    //aRegion.ImplAddRect( aSubRect );
-                    //aRectangles.push_back(aSubRect);
-                    //aRegion.Union(aSubRect);
-                }
-            }
-
-            if(aNewLine != aLine)
-            {
-                // need to write aLine, it's different from the next line
-                if(aLine.size())
-                {
-                    tools::Rectangle aSubRect;
-
-                    // enter y values and proceed ystart
-                    aSubRect.SetTop( nYStart );
-                    aSubRect.SetBottom( nY ? nY - 1 : 0 );
-
-                    for(size_t a(0); a < aLine.size();)
-                    {
-                        aSubRect.SetLeft( aLine[a++] );
-                        aSubRect.SetRight( aLine[a++] );
-                        aRegion.Union(aSubRect);
-                    }
-                }
-
-                // copy line as new line
-                aLine = aNewLine;
-                nYStart = nY;
-            }
-        }
-
-        // write last line if used
-        if(aLine.size())
-        {
-            tools::Rectangle aSubRect;
-
-            // enter y values
-            aSubRect.SetTop( nYStart );
-            aSubRect.SetBottom( nY ? nY - 1 : 0 );
-
-            for(size_t a(0); a < aLine.size();)
-            {
-                aSubRect.SetLeft( aLine[a++] );
-                aSubRect.SetRight( aLine[a++] );
-                aRegion.Union(aSubRect);
-            }
-        }
-
-        //aRegion.ImplEndAddRect();
-        //aRegion.SetRegionRectangles(aRectangles);
-
-        pReadAcc.reset();
-    }
-    else
-        aRegion = aRect;
-
-    return aRegion;
-}
-
-bool Bitmap::Replace( const Bitmap& rMask, const Color& rReplaceColor )
-{
-    ScopedReadAccess    pMaskAcc( const_cast<Bitmap&>(rMask) );
-    ScopedWriteAccess   pAcc(*this);
-    bool                bRet = false;
-
-    if( pMaskAcc && pAcc )
-    {
-        const long          nWidth = std::min( pMaskAcc->Width(), pAcc->Width() );
-        const long          nHeight = std::min( pMaskAcc->Height(), pAcc->Height() );
-        const BitmapColor   aMaskWhite( pMaskAcc->GetBestMatchingColor( COL_WHITE ) );
-        BitmapColor         aReplace;
-
-        if( pAcc->HasPalette() )
-        {
-            const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount();
-            const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount();
-
-            // default to the nearest color
-            aReplace = pAcc->GetBestMatchingColor( rReplaceColor );
-
-            // for paletted images without a matching palette entry
-            // look for an unused palette entry (NOTE: expensive!)
-            if( pAcc->GetPaletteColor( aReplace.GetIndex() ) != BitmapColor( rReplaceColor ) )
-            {
-                // if the palette has empty entries use the last one
-                if( nActColors < nMaxColors )
-                {
-                    pAcc->SetPaletteEntryCount( nActColors + 1 );
-                    pAcc->SetPaletteColor( nActColors, rReplaceColor );
-                    aReplace = BitmapColor( static_cast<sal_uInt8>(nActColors) );
-                }
-                else
-                {
-                    std::unique_ptr<bool[]> pFlags(new bool[ nMaxColors ]);
-
-                    // Set all entries to false
-                    std::fill( pFlags.get(), pFlags.get()+nMaxColors, false );
-
-                    for( long nY = 0; nY < nHeight; nY++ )
-                    {
-                        Scanline pScanline = pAcc->GetScanline(nY);
-                        for( long nX = 0; nX < nWidth; nX++ )
-                            pFlags[ pAcc->GetIndexFromData( pScanline, nX ) ] = true;
-                    }
-
-                    for( sal_uInt16 i = 0; i < nMaxColors; i++ )
-                    {
-                        // Hurray, we do have an unused entry
-                        if( !pFlags[ i ] )
-                        {
-                            pAcc->SetPaletteColor( i, rReplaceColor );
-                            aReplace = BitmapColor( static_cast<sal_uInt8>(i) );
-                        }
-                    }
-                }
-            }
-        }
-        else
-            aReplace = rReplaceColor;
-
-        for( long nY = 0; nY < nHeight; nY++ )
-        {
-            Scanline pScanline = pAcc->GetScanline( nY );
-            Scanline pScanlineMask = pMaskAcc->GetScanline( nY );
-            for( long nX = 0; nX < nWidth; nX++ )
-                if( pMaskAcc->GetPixelFromData( pScanlineMask, nX ) == aMaskWhite )
-                    pAcc->SetPixelOnData( pScanline, nX, aReplace );
-        }
-
-        bRet = true;
-    }
-
-    return bRet;
-}
-
-bool Bitmap::Replace( const AlphaMask& rAlpha, const Color& rMergeColor )
-{
-    Bitmap              aNewBmp( GetSizePixel(), 24 );
-    ScopedReadAccess    pAcc(*this);
-    AlphaMask::ScopedReadAccess pAlphaAcc(const_cast<AlphaMask&>(rAlpha));
-    ScopedWriteAccess   pNewAcc(aNewBmp);
-    bool                bRet = false;
-
-    if( pAcc && pAlphaAcc && pNewAcc )
-    {
-        BitmapColor aCol;
-        const long  nWidth = std::min( pAlphaAcc->Width(), pAcc->Width() );
-        const long  nHeight = std::min( pAlphaAcc->Height(), pAcc->Height() );
-
-        for( long nY = 0; nY < nHeight; nY++ )
-        {
-            Scanline pScanline = pNewAcc->GetScanline( nY );
-            Scanline pScanlineAlpha = pAlphaAcc->GetScanline( nY );
-            for( long nX = 0; nX < nWidth; nX++ )
-            {
-                aCol = pAcc->GetColor( nY, nX );
-                pNewAcc->SetPixelOnData( pScanline, nX, aCol.Merge( rMergeColor, 255 - pAlphaAcc->GetIndexFromData( pScanlineAlpha, nX ) ) );
-            }
-        }
-
-        bRet = true;
-    }
-
-    pAcc.reset();
-    pAlphaAcc.reset();
-    pNewAcc.reset();
-
-    if( bRet )
-    {
-        const MapMode   aMap( maPrefMapMode );
-        const Size      aSize( maPrefSize );
-
-        *this = aNewBmp;
-
-        maPrefMapMode = aMap;
-        maPrefSize = aSize;
-    }
-
-    return bRet;
-}
-
-bool Bitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol )
-{
-    if( mxImpBmp )
-    {
-        // implementation specific replace
-        std::shared_ptr<ImpBitmap> xImpBmp(new ImpBitmap);
-        if (xImpBmp->ImplCreate(*mxImpBmp) && xImpBmp->ImplReplace(rSearchColor, rReplaceColor, nTol))
-        {
-            ImplSetImpBitmap(xImpBmp);
-            maPrefMapMode = MapMode( MapUnit::MapPixel );
-            maPrefSize = xImpBmp->ImplGetSize();
-            return true;
-        }
-    }
-
-    // Bitmaps with 1 bit color depth can cause problems
-    // if they have other entries than black/white in their palette
-    if( 1 == GetBitCount() )
-        Convert( BmpConversion::N4BitColors );
-
-    ScopedWriteAccess   pAcc(*this);
-    bool                bRet = false;
-
-    if( pAcc )
-    {
-        const long  nMinR = MinMax<long>(rSearchColor.GetRed() - nTol, 0, 255);
-        const long  nMaxR = MinMax<long>(rSearchColor.GetRed() + nTol, 0, 255);
-        const long  nMinG = MinMax<long>(rSearchColor.GetGreen() - nTol, 0, 255);
-        const long  nMaxG = MinMax<long>(rSearchColor.GetGreen() + nTol, 0, 255);
-        const long  nMinB = MinMax<long>(rSearchColor.GetBlue() - nTol, 0, 255);
-        const long  nMaxB = MinMax<long>(rSearchColor.GetBlue() + nTol, 0, 255);
-
-        if( pAcc->HasPalette() )
-        {
-            for( sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++ )
-            {
-                const BitmapColor& rCol = pAcc->GetPaletteColor( i );
-
-                if( nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() &&
-                    nMinG <= rCol.GetGreen() && nMaxG >= rCol.GetGreen() &&
-                    nMinB <= rCol.GetBlue() && nMaxB >= rCol.GetBlue() )
-                {
-                    pAcc->SetPaletteColor( i, rReplaceColor );
-                }
-            }
-        }
-        else
-        {
-            BitmapColor         aCol;
-            const BitmapColor   aReplace( pAcc->GetBestMatchingColor( rReplaceColor ) );
-
-            for( long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++ )
-            {
-                Scanline pScanline = pAcc->GetScanline( nY );
-                for( long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++ )
-                {
-                    aCol = pAcc->GetPixelFromData( pScanline, nX );
-
-                    if( nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() &&
-                        nMinG <= aCol.GetGreen() && nMaxG >= aCol.GetGreen() &&
-                        nMinB <= aCol.GetBlue() && nMaxB >= aCol.GetBlue() )
-                    {
-                        pAcc->SetPixelOnData( pScanline, nX, aReplace );
-                    }
-                }
-            }
-        }
-
-        pAcc.reset();
-        bRet = true;
-    }
-
-    return bRet;
-}
-
-bool Bitmap::Replace( const Color* pSearchColors, const Color* pReplaceColors,
-                      sal_uLong nColorCount, sal_uInt8 const * pTols )
-{
-    // Bitmaps with 1 bit color depth can cause problems
-    // if they have other entries than black/white in their palette
-    if( 1 == GetBitCount() )
-        Convert( BmpConversion::N4BitColors );
-
-    ScopedWriteAccess   pAcc(*this);
-    bool                bRet = false;
-
-    if( pAcc )
-    {
-        std::unique_ptr<long[]> pMinR(new long[ nColorCount ]);
-        std::unique_ptr<long[]> pMaxR(new long[ nColorCount ]);
-        std::unique_ptr<long[]> pMinG(new long[ nColorCount ]);
-        std::unique_ptr<long[]> pMaxG(new long[ nColorCount ]);
-        std::unique_ptr<long[]> pMinB(new long[ nColorCount ]);
-        std::unique_ptr<long[]> pMaxB(new long[ nColorCount ]);
-
-        if( pTols )
-        {
-            for( sal_uLong i = 0; i < nColorCount; i++ )
-            {
-                const Color&    rCol = pSearchColors[ i ];
-                const sal_uInt8 nTol = pTols[ i ];
-
-                pMinR[ i ] = MinMax<long>(rCol.GetRed() - nTol, 0, 255);
-                pMaxR[ i ] = MinMax<long>(rCol.GetRed() + nTol, 0, 255);
-                pMinG[ i ] = MinMax<long>(rCol.GetGreen() - nTol, 0, 255);
-                pMaxG[ i ] = MinMax<long>(rCol.GetGreen() + nTol, 0, 255);
-                pMinB[ i ] = MinMax<long>(rCol.GetBlue() - nTol, 0, 255);
-                pMaxB[ i ] = MinMax<long>(rCol.GetBlue() + nTol, 0, 255);
-            }
-        }
-        else
-        {
-            for( sal_uLong i = 0; i < nColorCount; i++ )
-            {
-                const Color&    rCol = pSearchColors[ i ];
-
-                pMinR[ i ] = rCol.GetRed();
-                pMaxR[ i ] = rCol.GetRed();
-                pMinG[ i ] = rCol.GetGreen();
-                pMaxG[ i ] = rCol.GetGreen();
-                pMinB[ i ] = rCol.GetBlue();
-                pMaxB[ i ] = rCol.GetBlue();
-            }
-        }
-
-        if( pAcc->HasPalette() )
-        {
-            for( sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount(); nEntry < nPalCount; nEntry++ )
-            {
-                const BitmapColor& rCol = pAcc->GetPaletteColor( nEntry );
-
-                for( sal_uLong i = 0; i < nColorCount; i++ )
-                {
-                    if( pMinR[ i ] <= rCol.GetRed() && pMaxR[ i ] >= rCol.GetRed() &&
-                        pMinG[ i ] <= rCol.GetGreen() && pMaxG[ i ] >= rCol.GetGreen() &&
-                        pMinB[ i ] <= rCol.GetBlue() && pMaxB[ i ] >= rCol.GetBlue() )
-                    {
-                        pAcc->SetPaletteColor( nEntry, pReplaceColors[ i ] );
-                        break;
-                    }
-                }
-            }
-        }
-        else
-        {
-            BitmapColor     aCol;
-            std::unique_ptr<BitmapColor[]> pReplaces(new BitmapColor[ nColorCount ]);
-
-            for( sal_uLong i = 0; i < nColorCount; i++ )
-                pReplaces[ i ] = pAcc->GetBestMatchingColor( pReplaceColors[ i ] );
-
-            for( long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++ )
-            {
-                Scanline pScanline = pAcc->GetScanline( nY );
-                for( long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++ )
-                {
-                    aCol = pAcc->GetPixelFromData( pScanline, nX );
-
-                    for( sal_uLong i = 0; i < nColorCount; i++ )
-                    {
-                        if( pMinR[ i ] <= aCol.GetRed() && pMaxR[ i ] >= aCol.GetRed() &&
-                            pMinG[ i ] <= aCol.GetGreen() && pMaxG[ i ] >= aCol.GetGreen() &&
-                            pMinB[ i ] <= aCol.GetBlue() && pMaxB[ i ] >= aCol.GetBlue() )
-                        {
-                            pAcc->SetPixelOnData( pScanline, nX, pReplaces[ i ] );
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        pAcc.reset();
-        bRet = true;
-    }
-
-    return bRet;
-}
-
 Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
 {
     Bitmap aDispBmp( *this );
@@ -1817,102 +833,6 @@ Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay )
     return aDispBmp;
 }
 
-bool Bitmap::CombineSimple( const Bitmap& rMask, BmpCombine eCombine )
-{
-    ScopedReadAccess    pMaskAcc(const_cast<Bitmap&>(rMask));
-    ScopedWriteAccess   pAcc(*this);
-    bool                bRet = false;
-
-    if( pMaskAcc && pAcc )
-    {
-        const long          nWidth = std::min( pMaskAcc->Width(), pAcc->Width() );
-        const long          nHeight = std::min( pMaskAcc->Height(), pAcc->Height() );
-        const Color         aColBlack( COL_BLACK );
-        BitmapColor         aPixel;
-        BitmapColor         aMaskPixel;
-        const BitmapColor   aWhite( pAcc->GetBestMatchingColor( COL_WHITE ) );
-        const BitmapColor   aBlack( pAcc->GetBestMatchingColor( aColBlack ) );
-        const BitmapColor   aMaskBlack( pMaskAcc->GetBestMatchingColor( aColBlack ) );
-
-        switch( eCombine )
-        {
-            case BmpCombine::And:
-            {
-                for( long nY = 0; nY < nHeight; nY++ )
-                {
-                    Scanline pScanline = pAcc->GetScanline( nY );
-                    Scanline pScanlineMask = pMaskAcc->GetScanline( nY );
-                    for( long nX = 0; nX < nWidth; nX++ )
-                    {
-                        if( pMaskAcc->GetPixelFromData( pScanlineMask, nX ) != aMaskBlack && pAcc->GetPixelFromData( pScanline, nX ) != aBlack )
-                            pAcc->SetPixelOnData( pScanline, nX, aWhite );
-                        else
-                            pAcc->SetPixelOnData( pScanline, nX, aBlack );
-                    }
-                }
-            }
-            break;
-
-            case BmpCombine::Or:
-            {
-                for( long nY = 0; nY < nHeight; nY++ )
-                {
-                    Scanline pScanline = pAcc->GetScanline( nY );
-                    Scanline pScanlineMask = pMaskAcc->GetScanline( nY );
-                    for( long nX = 0; nX < nWidth; nX++ )
-                    {
-                        if( pMaskAcc->GetPixelFromData( pScanlineMask, nX ) != aMaskBlack || pAcc->GetPixelFromData( pScanline, nX ) != aBlack )
-                            pAcc->SetPixelOnData( pScanline, nX, aWhite );
-                        else
-                            pAcc->SetPixelOnData( pScanline, nX, aBlack );
-                    }
-                }
-            }
-            break;
-
-        }
-
-        bRet = true;
-    }
-
-    return bRet;
-}
-
-// TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
-// optimizations. Might even consolidate the code here and there.
-bool Bitmap::Blend( const AlphaMask& rAlpha, const Color& rBackgroundColor )
-{
-    // Convert to a truecolor bitmap, if we're a paletted one. There's
-    // room for tradeoff decision here, maybe later for an overload (or a flag)
-    if( GetBitCount() <= 8 )
-        Convert( BmpConversion::N24Bit );
-
-    AlphaMask::ScopedReadAccess pAlphaAcc(const_cast<AlphaMask&>(rAlpha));
-
-    ScopedWriteAccess   pAcc(*this);
-    bool                bRet = false;
-
-    if( pAlphaAcc && pAcc )
-    {
-        const long          nWidth = std::min( pAlphaAcc->Width(), pAcc->Width() );
-        const long          nHeight = std::min( pAlphaAcc->Height(), pAcc->Height() );
-
-        for( long nY = 0; nY < nHeight; ++nY )
-        {
-            Scanline pScanline = pAcc->GetScanline( nY );
-            Scanline pScanlineAlpha = pAlphaAcc->GetScanline( nY );
-            for( long nX = 0; nX < nWidth; ++nX )
-                pAcc->SetPixelOnData( pScanline, nX,
-                                pAcc->GetPixelFromData( pScanline, nX ).Merge( rBackgroundColor,
-                                                                255 - pAlphaAcc->GetIndexFromData( pScanlineAlpha, nX ) ) );
-        }
-
-        bRet = true;
-    }
-
-    return bRet;
-}
-
 bool Bitmap::MakeMonochrome(sal_uInt8 cThreshold)
 {
     ScopedReadAccess pReadAcc(*this);
diff --git a/vcl/source/bitmap/bitmappaint.cxx b/vcl/source/bitmap/bitmappaint.cxx
new file mode 100644
index 000000000000..38472333a0c3
--- /dev/null
+++ b/vcl/source/bitmap/bitmappaint.cxx
@@ -0,0 +1,1158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <tools/poly.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/alpha.hxx>
+
+#include <impbmp.hxx>
+
+#include <algorithm>
+#include <memory>
+
+bool Bitmap::Erase(const Color& rFillColor)
+{
+    if (IsEmpty())
+        return true;
+
+    Bitmap::ScopedWriteAccess pWriteAcc(*this);
+    bool bRet = false;
+
+    if (pWriteAcc)
+    {
+        const ScanlineFormat nFormat = pWriteAcc->GetScanlineFormat();
+        sal_uInt8 cIndex = 0;
+        bool bFast = false;
+
+        switch (nFormat)
+        {
+            case ScanlineFormat::N1BitMsbPal:
+            case ScanlineFormat::N1BitLsbPal:
+            {
+                cIndex = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex(rFillColor));
+                cIndex = (cIndex ? 255 : 0);
+                bFast = true;
+            }
+            break;
+
+            case ScanlineFormat::N4BitMsnPal:
+            case ScanlineFormat::N4BitLsnPal:
+            {
+                cIndex = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex(rFillColor));
+                cIndex = cIndex | (cIndex << 4);
+                bFast = true;
+            }
+            break;
+
+            case ScanlineFormat::N8BitPal:
+            {
+                cIndex = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex(rFillColor));
+                bFast = true;
+            }
+            break;
+
+            case ScanlineFormat::N24BitTcBgr:
+            case ScanlineFormat::N24BitTcRgb:
+            {
+                if (rFillColor.GetRed() == rFillColor.GetGreen()
+                    && rFillColor.GetRed() == rFillColor.GetBlue())
+                {
+                    cIndex = rFillColor.GetRed();
+                    bFast = true;
+                }
+                else
+                {
+                    bFast = false;
+                }
+            }
+            break;
+
+            default:
+                bFast = false;
+                break;
+        }
+
+        if (bFast)
+        {
+            const sal_uLong nBufSize = pWriteAcc->GetScanlineSize() * pWriteAcc->Height();
+            memset(pWriteAcc->GetBuffer(), cIndex, nBufSize);
+        }
+        else
+        {
+            const tools::Rectangle aRect(Point(), Size(pWriteAcc->Width(), pWriteAcc->Height()));
+            pWriteAcc->SetFillColor(rFillColor);
+            pWriteAcc->FillRect(aRect);
+        }
+
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+bool Bitmap::Invert()
+{
+    ScopedWriteAccess pAcc(*this);
+    bool bRet = false;
+
+    if (pAcc)
+    {
+        if (pAcc->HasPalette())
+        {
+            BitmapPalette aBmpPal(pAcc->GetPalette());
+            const sal_uInt16 nCount = aBmpPal.GetEntryCount();
+
+            for (sal_uInt16 i = 0; i < nCount; i++)
+            {
+                aBmpPal[i].Invert();
+            }
+
+            pAcc->SetPalette(aBmpPal);
+        }
+        else
+        {
+            const long nWidth = pAcc->Width();
+            const long nHeight = pAcc->Height();
+
+            for (long nY = 0; nY < nHeight; nY++)
+            {
+                Scanline pScanline = pAcc->GetScanline(nY);
+                for (long nX = 0; nX < nWidth; nX++)
+                {
+                    pAcc->SetPixelOnData(pScanline, nX,
+                                         pAcc->GetPixelFromData(pScanline, nX).Invert());
+                }
+            }
+        }
+
+        mxImpBmp->ImplInvalidateChecksum();
+        pAcc.reset();
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+bool Bitmap::Mirror(BmpMirrorFlags nMirrorFlags)
+{
+    bool bHorz(nMirrorFlags & BmpMirrorFlags::Horizontal);
+    bool bVert(nMirrorFlags & BmpMirrorFlags::Vertical);
+    bool bRet = false;
+
+    if (bHorz && !bVert)
+    {
+        ScopedWriteAccess pAcc(*this);
+
+        if (pAcc)
+        {
+            const long nWidth = pAcc->Width();
+            const long nHeight = pAcc->Height();
+            const long nWidth1 = nWidth - 1;
+            const long nWidth_2 = nWidth >> 1;
+
+            for (long nY = 0; nY < nHeight; nY++)
+            {
+                Scanline pScanline = pAcc->GetScanline(nY);
+                for (long nX = 0, nOther = nWidth1; nX < nWidth_2; nX++, nOther--)
+                {
+                    const BitmapColor aTemp(pAcc->GetPixelFromData(pScanline, nX));
+
+                    pAcc->SetPixelOnData(pScanline, nX, pAcc->GetPixelFromData(pScanline, nOther));
+                    pAcc->SetPixelOnData(pScanline, nOther, aTemp);
+                }
+            }
+
+            pAcc.reset();
+            bRet = true;
+        }
+    }
+    else if (bVert && !bHorz)
+    {
+        ScopedWriteAccess pAcc(*this);
+
+        if (pAcc)
+        {
+            const long nScanSize = pAcc->GetScanlineSize();
+            std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nScanSize]);
+            const long nHeight = pAcc->Height();
+            const long nHeight1 = nHeight - 1;
+            const long nHeight_2 = nHeight >> 1;
+
+            for (long nY = 0, nOther = nHeight1; nY < nHeight_2; nY++, nOther--)
+            {
+                memcpy(pBuffer.get(), pAcc->GetScanline(nY), nScanSize);
+                memcpy(pAcc->GetScanline(nY), pAcc->GetScanline(nOther), nScanSize);
+                memcpy(pAcc->GetScanline(nOther), pBuffer.get(), nScanSize);
+            }
+
+            pAcc.reset();
+            bRet = true;
+        }
+    }
+    else if (bHorz && bVert)
+    {
+        ScopedWriteAccess pAcc(*this);
+
+        if (pAcc)
+        {
+            const long nWidth = pAcc->Width();
+            const long nWidth1 = nWidth - 1;
+            const long nHeight = pAcc->Height();
+            long nHeight_2 = nHeight >> 1;
+
+            for (long nY = 0, nOtherY = nHeight - 1; nY < nHeight_2; nY++, nOtherY--)
+            {
+                Scanline pScanline = pAcc->GetScanline(nY);
+                Scanline pScanlineOther = pAcc->GetScanline(nOtherY);
+                for (long nX = 0, nOtherX = nWidth1; nX < nWidth; nX++, nOtherX--)
+                {
+                    const BitmapColor aTemp(pAcc->GetPixelFromData(pScanline, nX));
+
+                    pAcc->SetPixelOnData(pScanline, nX,
+                                         pAcc->GetPixelFromData(pScanlineOther, nOtherX));
+                    pAcc->SetPixelOnData(pScanlineOther, nOtherX, aTemp);
+                }
+            }
+
+            // if necessary, also mirror the middle line horizontally
+            if (nHeight & 1)
+            {
+                Scanline pScanline = pAcc->GetScanline(nHeight_2);
+                for (long nX = 0, nOtherX = nWidth1, nWidth_2 = nWidth >> 1; nX < nWidth_2;
+                     nX++, nOtherX--)
+                {
+                    const BitmapColor aTemp(pAcc->GetPixelFromData(pScanline, nX));
+                    pAcc->SetPixelOnData(pScanline, nX, pAcc->GetPixelFromData(pScanline, nOtherX));
+                    pAcc->SetPixelOnData(pScanline, nOtherX, aTemp);
+                }
+            }
+
+            pAcc.reset();
+            bRet = true;
+        }
+    }
+    else
+        bRet = true;
+
+    return bRet;
+}
+
+bool Bitmap::Rotate(long nAngle10, const Color& rFillColor)
+{
+    bool bRet = false;
+
+    nAngle10 %= 3600;
+    nAngle10 = (nAngle10 < 0) ? (3599L + nAngle10) : nAngle10;
+
+    if (!nAngle10)
+        bRet = true;
+    else if (nAngle10 == 1800)
+        bRet = Mirror(BmpMirrorFlags::Horizontal | BmpMirrorFlags::Vertical);
+    else
+    {
+        ScopedReadAccess pReadAcc(*this);
+        Bitmap aRotatedBmp;
+
+        if (pReadAcc)
+        {
+            const Size aSizePix(GetSizePixel());
+
+            if (nAngle10 == 900 || nAngle10 == 2700)
+            {
+                const Size aNewSizePix(aSizePix.Height(), aSizePix.Width());
+                Bitmap aNewBmp(aNewSizePix, GetBitCount(), &pReadAcc->GetPalette());
+                ScopedWriteAccess pWriteAcc(aNewBmp);
+
+                if (pWriteAcc)
+                {
+                    const long nWidth = aSizePix.Width();
+                    const long nWidth1 = nWidth - 1;
+                    const long nHeight = aSizePix.Height();
+                    const long nHeight1 = nHeight - 1;
+                    const long nNewWidth = aNewSizePix.Width();
+                    const long nNewHeight = aNewSizePix.Height();
+
+                    if (nAngle10 == 900)
+                    {
+                        for (long nY = 0, nOtherX = nWidth1; nY < nNewHeight; nY++, nOtherX--)
+                        {
+                            Scanline pScanline = pWriteAcc->GetScanline(nY);
+                            for (long nX = 0, nOtherY = 0; nX < nNewWidth; nX++)
+                            {
+                                pWriteAcc->SetPixelOnData(pScanline, nX,
+                                                          pReadAcc->GetPixel(nOtherY++, nOtherX));
+                            }
+                        }
+                    }
+                    else if (nAngle10 == 2700)
+                    {
+                        for (long nY = 0, nOtherX = 0; nY < nNewHeight; nY++, nOtherX++)
+                        {
+                            Scanline pScanline = pWriteAcc->GetScanline(nY);
+                            for (long nX = 0, nOtherY = nHeight1; nX < nNewWidth; nX++)
+                            {
+                                pWriteAcc->SetPixelOnData(pScanline, nX,
+                                                          pReadAcc->GetPixel(nOtherY--, nOtherX));
+                            }
+                        }
+                    }
+
+                    pWriteAcc.reset();
+                }
+
+                aRotatedBmp = aNewBmp;
+            }
+            else
+            {
+                Point aTmpPoint;
+                tools::Rectangle aTmpRectangle(aTmpPoint, aSizePix);
+                tools::Polygon aPoly(aTmpRectangle);
+                aPoly.Rotate(aTmpPoint, static_cast<sal_uInt16>(nAngle10));
+
+                tools::Rectangle aNewBound(aPoly.GetBoundRect());
+                const Size aNewSizePix(aNewBound.GetSize());
+                Bitmap aNewBmp(aNewSizePix, GetBitCount(), &pReadAcc->GetPalette());
+                ScopedWriteAccess pWriteAcc(aNewBmp);
+
+                if (pWriteAcc)
+                {
+                    const BitmapColor aFillColor(pWriteAcc->GetBestMatchingColor(rFillColor));
+                    const double fCosAngle = cos(nAngle10 * F_PI1800);
+                    const double fSinAngle = sin(nAngle10 * F_PI1800);
+                    const double fXMin = aNewBound.Left();
+                    const double fYMin = aNewBound.Top();
+                    const long nWidth = aSizePix.Width();
+                    const long nHeight = aSizePix.Height();
+                    const long nNewWidth = aNewSizePix.Width();
+                    const long nNewHeight = aNewSizePix.Height();
+                    long nX;
+                    long nY;
+                    long nRotX;
+                    long nRotY;
+                    std::unique_ptr<long[]> pCosX(new long[nNewWidth]);
+                    std::unique_ptr<long[]> pSinX(new long[nNewWidth]);
+                    std::unique_ptr<long[]> pCosY(new long[nNewHeight]);
+                    std::unique_ptr<long[]> pSinY(new long[nNewHeight]);
+
+                    for (nX = 0; nX < nNewWidth; nX++)
+                    {
+                        const double fTmp = (fXMin + nX) * 64.;
+
+                        pCosX[nX] = FRound(fCosAngle * fTmp);
+                        pSinX[nX] = FRound(fSinAngle * fTmp);
+                    }
+
+                    for (nY = 0; nY < nNewHeight; nY++)
+                    {
+                        const double fTmp = (fYMin + nY) * 64.;
+
+                        pCosY[nY] = FRound(fCosAngle * fTmp);
+                        pSinY[nY] = FRound(fSinAngle * fTmp);
+                    }
+
+                    for (nY = 0; nY < nNewHeight; nY++)
+                    {
+                        long nSinY = pSinY[nY];
+                        long nCosY = pCosY[nY];
+                        Scanline pScanline = pWriteAcc->GetScanline(nY);
+
+                        for (nX = 0; nX < nNewWidth; nX++)
+                        {
+                            nRotX = (pCosX[nX] - nSinY) >> 6;
+                            nRotY = (pSinX[nX] + nCosY) >> 6;
+
+                            if ((nRotX > -1) && (nRotX < nWidth) && (nRotY > -1)
+                                && (nRotY < nHeight))
+                            {
+                                pWriteAcc->SetPixelOnData(pScanline, nX,
+                                                          pReadAcc->GetPixel(nRotY, nRotX));
+                            }
+                            else
+                            {
+                                pWriteAcc->SetPixelOnData(pScanline, nX, aFillColor);
+                            }
+                        }
+                    }
+
+                    pWriteAcc.reset();
+                }
+
+                aRotatedBmp = aNewBmp;
+            }
+
+            pReadAcc.reset();
+        }
+
+        bRet = !!aRotatedBmp;
+        if (bRet)
+            ImplAssignWithSize(aRotatedBmp);
+    }
+
+    return bRet;
+};
+
+Bitmap Bitmap::CreateMask(const Color& rTransColor, sal_uInt8 nTol) const
+{
+    ScopedReadAccess pReadAcc(const_cast<Bitmap&>(*this));
+
+    if (!nTol && pReadAcc
+        && (pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitLsbPal
+            || pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal)
+        && pReadAcc->GetBestMatchingColor(COL_WHITE) == pReadAcc->GetBestMatchingColor(rTransColor))
+    {
+        // if we're a 1 bit pixel already, and the transcolor matches the color that would replace it
+        // already, then just return a copy
+        return *this;
+    }
+
+    Bitmap aNewBmp(GetSizePixel(), 1);
+    ScopedWriteAccess pWriteAcc(aNewBmp);
+    bool bRet = false;
+
+    if (pWriteAcc && pReadAcc)
+    {
+        const long nWidth = pReadAcc->Width();
+        const long nHeight = pReadAcc->Height();
+        const BitmapColor aBlack(pWriteAcc->GetBestMatchingColor(COL_BLACK));
+        const BitmapColor aWhite(pWriteAcc->GetBestMatchingColor(COL_WHITE));
+
+        if (!nTol)
+        {
+            const BitmapColor aTest(pReadAcc->GetBestMatchingColor(rTransColor));
+
+            if (pReadAcc->GetScanlineFormat() == ScanlineFormat::N4BitMsnPal
+                || pReadAcc->GetScanlineFormat() == ScanlineFormat::N4BitLsnPal)
+            {
+                // optimized for 4Bit-MSN/LSN source palette
+                const sal_uInt8 cTest = aTest.GetIndex();
+                const long nShiftInit
+                    = ((pReadAcc->GetScanlineFormat() == ScanlineFormat::N4BitMsnPal) ? 4 : 0);
+
+                if (pWriteAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal
+                    && aWhite.GetIndex() == 1)
+                {
+                    // optimized for 1Bit-MSB destination palette
+                    for (long nY = 0; nY < nHeight; ++nY)
+                    {
+                        Scanline pSrc = pReadAcc->GetScanline(nY);
+                        Scanline pDst = pWriteAcc->GetScanline(nY);
+                        for (long nX = 0, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4)
+                        {
+                            if (cTest == ((pSrc[nX >> 1] >> nShift) & 0x0f))
+                                pDst[nX >> 3] |= 1 << (7 - (nX & 7));
+                            else
+                                pDst[nX >> 3] &= ~(1 << (7 - (nX & 7)));
+                        }
+                    }
+                }
+                else
+                {
+                    for (long nY = 0; nY < nHeight; ++nY)
+                    {
+                        Scanline pSrc = pReadAcc->GetScanline(nY);
+                        Scanline pDst = pWriteAcc->GetScanline(nY);
+                        for (long nX = 0, nShift = nShiftInit; nX < nWidth; nX++, nShift ^= 4)
+                        {
+                            if (cTest == ((pSrc[nX >> 1] >> nShift) & 0x0f))
+                                pWriteAcc->SetPixelOnData(pDst, nX, aWhite);
+                            else
+                                pWriteAcc->SetPixelOnData(pDst, nX, aBlack);
+                        }
+                    }
+                }
+            }
+            else if (pReadAcc->GetScanlineFormat() == ScanlineFormat::N8BitPal)
+            {
+                // optimized for 8Bit source palette
+                const sal_uInt8 cTest = aTest.GetIndex();
+
+                if (pWriteAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal
+                    && aWhite.GetIndex() == 1)
+                {
+                    // optimized for 1Bit-MSB destination palette
+                    for (long nY = 0; nY < nHeight; ++nY)
+                    {
+                        Scanline pSrc = pReadAcc->GetScanline(nY);
+                        Scanline pDst = pWriteAcc->GetScanline(nY);
+                        for (long nX = 0; nX < nWidth; ++nX)
+                        {
+                            if (cTest == pSrc[nX])
+                                pDst[nX >> 3] |= 1 << (7 - (nX & 7));
+                            else
+                                pDst[nX >> 3] &= ~(1 << (7 - (nX & 7)));
+                        }
+                    }
+                }
+                else
+                {
+                    for (long nY = 0; nY < nHeight; ++nY)
+                    {
+                        Scanline pSrc = pReadAcc->GetScanline(nY);
+                        Scanline pDst = pWriteAcc->GetScanline(nY);
+                        for (long nX = 0; nX < nWidth; ++nX)
+                        {
+                            if (cTest == pSrc[nX])
+                                pWriteAcc->SetPixelOnData(pDst, nX, aWhite);
+                            else
+                                pWriteAcc->SetPixelOnData(pDst, nX, aBlack);
+                        }
+                    }
+                }
+            }
+            else if (pWriteAcc->GetScanlineFormat() == pReadAcc->GetScanlineFormat()
+                     && aWhite.GetIndex() == 1
+                     && (pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitLsbPal
+                         || pReadAcc->GetScanlineFormat() == ScanlineFormat::N1BitMsbPal))
+            {
+                for (long nY = 0; nY < nHeight; ++nY)
+                {
+                    Scanline pSrc = pReadAcc->GetScanline(nY);
+                    Scanline pDst = pWriteAcc->GetScanline(nY);
+                    assert(pWriteAcc->GetScanlineSize() == pReadAcc->GetScanlineSize());
+                    const long nScanlineSize = pWriteAcc->GetScanlineSize();
+                    for (long nX = 0; nX < nScanlineSize; ++nX)
+                        pDst[nX] = ~pSrc[nX];
+                }
+            }
+            else
+            {
+                // not optimized
+                for (long nY = 0; nY < nHeight; ++nY)
+                {
+                    Scanline pScanline = pWriteAcc->GetScanline(nY);
+                    Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+                    for (long nX = 0; nX < nWidth; ++nX)
+                    {
+                        if (aTest == pReadAcc->GetPixelFromData(pScanlineRead, nX))
+                            pWriteAcc->SetPixelOnData(pScanline, nX, aWhite);
+                        else
+                            pWriteAcc->SetPixelOnData(pScanline, nX, aBlack);
+                    }
+                }
+            }
+        }
+        else
+        {
+            BitmapColor aCol;
+            long nR, nG, nB;
+            const long nMinR = MinMax<long>(rTransColor.GetRed() - nTol, 0, 255);
+            const long nMaxR = MinMax<long>(rTransColor.GetRed() + nTol, 0, 255);
+            const long nMinG = MinMax<long>(rTransColor.GetGreen() - nTol, 0, 255);
+            const long nMaxG = MinMax<long>(rTransColor.GetGreen() + nTol, 0, 255);
+            const long nMinB = MinMax<long>(rTransColor.GetBlue() - nTol, 0, 255);
+            const long nMaxB = MinMax<long>(rTransColor.GetBlue() + nTol, 0, 255);
+
+            if (pReadAcc->HasPalette())
+            {
+                for (long nY = 0; nY < nHeight; nY++)
+                {
+                    Scanline pScanline = pWriteAcc->GetScanline(nY);
+                    Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+                    for (long nX = 0; nX < nWidth; nX++)
+                    {
+                        aCol = pReadAcc->GetPaletteColor(
+                            pReadAcc->GetIndexFromData(pScanlineRead, nX));
+                        nR = aCol.GetRed();
+                        nG = aCol.GetGreen();
+                        nB = aCol.GetBlue();
+
+                        if (nMinR <= nR && nMaxR >= nR && nMinG <= nG && nMaxG >= nG && nMinB <= nB
+                            && nMaxB >= nB)
+                        {
+                            pWriteAcc->SetPixelOnData(pScanline, nX, aWhite);
+                        }
+                        else
+                        {
+                            pWriteAcc->SetPixelOnData(pScanline, nX, aBlack);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (long nY = 0; nY < nHeight; nY++)
+                {
+                    Scanline pScanline = pWriteAcc->GetScanline(nY);
+                    Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+                    for (long nX = 0; nX < nWidth; nX++)
+                    {
+                        aCol = pReadAcc->GetPixelFromData(pScanlineRead, nX);
+                        nR = aCol.GetRed();
+                        nG = aCol.GetGreen();
+                        nB = aCol.GetBlue();
+
+                        if (nMinR <= nR && nMaxR >= nR && nMinG <= nG && nMaxG >= nG && nMinB <= nB
+                            && nMaxB >= nB)
+                        {
+                            pWriteAcc->SetPixelOnData(pScanline, nX, aWhite);
+                        }
+                        else
+                        {
+                            pWriteAcc->SetPixelOnData(pScanline, nX, aBlack);
+                        }
+                    }
+                }
+            }
+        }
+
+        bRet = true;
+    }
+
+    pWriteAcc.reset();
+    pReadAcc.reset();
+
+    if (bRet)
+    {
+        aNewBmp.maPrefSize = maPrefSize;
+        aNewBmp.maPrefMapMode = maPrefMapMode;
+    }
+    else
+        aNewBmp = Bitmap();
+
+    return aNewBmp;
+}
+
+vcl::Region Bitmap::CreateRegion(const Color& rColor, const tools::Rectangle& rRect) const
+{
+    vcl::Region aRegion;
+    tools::Rectangle aRect(rRect);
+    ScopedReadAccess pReadAcc(const_cast<Bitmap&>(*this));
+
+    aRect.Intersection(tools::Rectangle(Point(), GetSizePixel()));
+    aRect.Justify();
+
+    if (pReadAcc)
+    {
+        const long nLeft = aRect.Left();
+        const long nTop = aRect.Top();
+        const long nRight = aRect.Right();
+        const long nBottom = aRect.Bottom();
+        const BitmapColor aMatch(pReadAcc->GetBestMatchingColor(rColor));
+
+        //RectangleVector aRectangles;
+        //aRegion.ImplBeginAddRect();
+        std::vector<long> aLine;
+        long nYStart(nTop);
+        long nY(nTop);
+
+        for (; nY <= nBottom; nY++)
+        {
+            //aSubRect.Top() = aSubRect.Bottom() = nY;
+            std::vector<long> aNewLine;
+            long nX(nLeft);
+            Scanline pScanlineRead = pReadAcc->GetScanline(nY);
+
+            for (; nX <= nRight;)
+            {
+                while ((nX <= nRight) && (aMatch != pReadAcc->GetPixelFromData(pScanlineRead, nX)))
+                    nX++;
+
+                if (nX <= nRight)
+                {
+                    aNewLine.push_back(nX);
+                    //aSubRect.Left() = nX;
+
+                    while ((nX <= nRight)
+                           && (aMatch == pReadAcc->GetPixelFromData(pScanlineRead, nX)))
+                    {
+                        nX++;
+                    }
+
+                    //aSubRect.Right() = nX - 1;
+                    aNewLine.push_back(nX - 1);
+
+                    //aRegion.ImplAddRect( aSubRect );
+                    //aRectangles.push_back(aSubRect);
+                    //aRegion.Union(aSubRect);
+                }
+            }
+
+            if (aNewLine != aLine)
+            {
+                // need to write aLine, it's different from the next line
+                if (aLine.size())
+                {
+                    tools::Rectangle aSubRect;
+
+                    // enter y values and proceed ystart
+                    aSubRect.SetTop(nYStart);
+                    aSubRect.SetBottom(nY ? nY - 1 : 0);
+
+                    for (size_t a(0); a < aLine.size();)
+                    {
+                        aSubRect.SetLeft(aLine[a++]);
+                        aSubRect.SetRight(aLine[a++]);
+                        aRegion.Union(aSubRect);
+                    }
+                }
+
+                // copy line as new line
+                aLine = aNewLine;
+                nYStart = nY;
+            }
+        }
+
+        // write last line if used
+        if (aLine.size())
+        {
+            tools::Rectangle aSubRect;
+
+            // enter y values
+            aSubRect.SetTop(nYStart);
+            aSubRect.SetBottom(nY ? nY - 1 : 0);
+
+            for (size_t a(0); a < aLine.size();)
+            {
+                aSubRect.SetLeft(aLine[a++]);
+                aSubRect.SetRight(aLine[a++]);
+                aRegion.Union(aSubRect);
+            }
+        }
+
+        //aRegion.ImplEndAddRect();
+        //aRegion.SetRegionRectangles(aRectangles);
+
+        pReadAcc.reset();
+    }
+    else
+    {
+        aRegion = aRect;
+    }
+
+    return aRegion;
+}
+
+bool Bitmap::Replace(const Bitmap& rMask, const Color& rReplaceColor)
+{
+    ScopedReadAccess pMaskAcc(const_cast<Bitmap&>(rMask));
+    ScopedWriteAccess pAcc(*this);
+    bool bRet = false;
+
+    if (pMaskAcc && pAcc)
+    {
+        const long nWidth = std::min(pMaskAcc->Width(), pAcc->Width());
+        const long nHeight = std::min(pMaskAcc->Height(), pAcc->Height());
+        const BitmapColor aMaskWhite(pMaskAcc->GetBestMatchingColor(COL_WHITE));
+        BitmapColor aReplace;
+
+        if (pAcc->HasPalette())
+        {
+            const sal_uInt16 nActColors = pAcc->GetPaletteEntryCount();
+            const sal_uInt16 nMaxColors = 1 << pAcc->GetBitCount();
+
+            // default to the nearest color
+            aReplace = pAcc->GetBestMatchingColor(rReplaceColor);
+
+            // for paletted images without a matching palette entry
+            // look for an unused palette entry (NOTE: expensive!)
+            if (pAcc->GetPaletteColor(aReplace.GetIndex()) != BitmapColor(rReplaceColor))
+            {
+                // if the palette has empty entries use the last one
+                if (nActColors < nMaxColors)
+                {
+                    pAcc->SetPaletteEntryCount(nActColors + 1);
+                    pAcc->SetPaletteColor(nActColors, rReplaceColor);
+                    aReplace = BitmapColor(static_cast<sal_uInt8>(nActColors));
+                }
+                else
+                {
+                    std::unique_ptr<bool[]> pFlags(new bool[nMaxColors]);
+
+                    // Set all entries to false
+                    std::fill(pFlags.get(), pFlags.get() + nMaxColors, false);
+
+                    for (long nY = 0; nY < nHeight; nY++)
+                    {
+                        Scanline pScanline = pAcc->GetScanline(nY);
+                        for (long nX = 0; nX < nWidth; nX++)
+                            pFlags[pAcc->GetIndexFromData(pScanline, nX)] = true;
+                    }
+
+                    for (sal_uInt16 i = 0; i < nMaxColors; i++)
+                    {
+                        // Hurray, we do have an unused entry
+                        if (!pFlags[i])
+                        {
+                            pAcc->SetPaletteColor(i, rReplaceColor);
+                            aReplace = BitmapColor(static_cast<sal_uInt8>(i));
+                        }
+                    }
+                }
+            }
+        }
+        else
+            aReplace = rReplaceColor;
+
+        for (long nY = 0; nY < nHeight; nY++)
+        {
+            Scanline pScanline = pAcc->GetScanline(nY);
+            Scanline pScanlineMask = pMaskAcc->GetScanline(nY);
+            for (long nX = 0; nX < nWidth; nX++)
+            {
+                if (pMaskAcc->GetPixelFromData(pScanlineMask, nX) == aMaskWhite)
+                    pAcc->SetPixelOnData(pScanline, nX, aReplace);
+            }
+        }
+
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+bool Bitmap::Replace(const AlphaMask& rAlpha, const Color& rMergeColor)
+{
+    Bitmap aNewBmp(GetSizePixel(), 24);
+    ScopedReadAccess pAcc(*this);
+    AlphaMask::ScopedReadAccess pAlphaAcc(const_cast<AlphaMask&>(rAlpha));
+    ScopedWriteAccess pNewAcc(aNewBmp);
+    bool bRet = false;
+
+    if (pAcc && pAlphaAcc && pNewAcc)
+    {
+        BitmapColor aCol;
+        const long nWidth = std::min(pAlphaAcc->Width(), pAcc->Width());
+        const long nHeight = std::min(pAlphaAcc->Height(), pAcc->Height());
+
+        for (long nY = 0; nY < nHeight; nY++)
+        {
+            Scanline pScanline = pNewAcc->GetScanline(nY);
+            Scanline pScanlineAlpha = pAlphaAcc->GetScanline(nY);
+            for (long nX = 0; nX < nWidth; nX++)
+            {
+                aCol = pAcc->GetColor(nY, nX);
+                pNewAcc->SetPixelOnData(
+                    pScanline, nX,
+                    aCol.Merge(rMergeColor, 255 - pAlphaAcc->GetIndexFromData(pScanlineAlpha, nX)));
+            }
+        }
+
+        bRet = true;
+    }
+
+    pAcc.reset();
+    pAlphaAcc.reset();
+    pNewAcc.reset();
+
+    if (bRet)
+    {
+        const MapMode aMap(maPrefMapMode);
+        const Size aSize(maPrefSize);
+
+        *this = aNewBmp;
+
+        maPrefMapMode = aMap;
+        maPrefSize = aSize;
+    }
+
+    return bRet;
+}
+
+bool Bitmap::Replace(const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol)
+{
+    if (mxImpBmp)
+    {
+        // implementation specific replace
+        std::shared_ptr<ImpBitmap> xImpBmp(new ImpBitmap);
+        if (xImpBmp->ImplCreate(*mxImpBmp)
+            && xImpBmp->ImplReplace(rSearchColor, rReplaceColor, nTol))
+        {
+            ImplSetImpBitmap(xImpBmp);
+            maPrefMapMode = MapMode(MapUnit::MapPixel);
+            maPrefSize = xImpBmp->ImplGetSize();
+            return true;
+        }
+    }
+
+    // Bitmaps with 1 bit color depth can cause problems if they have other entries than black/white
+    // in their palette
+    if (GetBitCount() == 1)
+        Convert(BmpConversion::N4BitColors);
+
+    ScopedWriteAccess pAcc(*this);
+    bool bRet = false;
+
+    if (pAcc)
+    {
+        const long nMinR = MinMax<long>(rSearchColor.GetRed() - nTol, 0, 255);
+        const long nMaxR = MinMax<long>(rSearchColor.GetRed() + nTol, 0, 255);
+        const long nMinG = MinMax<long>(rSearchColor.GetGreen() - nTol, 0, 255);
+        const long nMaxG = MinMax<long>(rSearchColor.GetGreen() + nTol, 0, 255);
+        const long nMinB = MinMax<long>(rSearchColor.GetBlue() - nTol, 0, 255);
+        const long nMaxB = MinMax<long>(rSearchColor.GetBlue() + nTol, 0, 255);
+
+        if (pAcc->HasPalette())
+        {
+            for (sal_uInt16 i = 0, nPalCount = pAcc->GetPaletteEntryCount(); i < nPalCount; i++)
+            {
+                const BitmapColor& rCol = pAcc->GetPaletteColor(i);
+
+                if (nMinR <= rCol.GetRed() && nMaxR >= rCol.GetRed() && nMinG <= rCol.GetGreen()
+                    && nMaxG >= rCol.GetGreen() && nMinB <= rCol.GetBlue()
+                    && nMaxB >= rCol.GetBlue())
+                {
+                    pAcc->SetPaletteColor(i, rReplaceColor);
+                }
+            }
+        }
+        else
+        {
+            BitmapColor aCol;
+            const BitmapColor aReplace(pAcc->GetBestMatchingColor(rReplaceColor));
+
+            for (long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++)
+            {
+                Scanline pScanline = pAcc->GetScanline(nY);
+                for (long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++)
+                {
+                    aCol = pAcc->GetPixelFromData(pScanline, nX);
+
+                    if (nMinR <= aCol.GetRed() && nMaxR >= aCol.GetRed() && nMinG <= aCol.GetGreen()
+                        && nMaxG >= aCol.GetGreen() && nMinB <= aCol.GetBlue()
+                        && nMaxB >= aCol.GetBlue())
+                    {
+                        pAcc->SetPixelOnData(pScanline, nX, aReplace);
+                    }
+                }
+            }
+        }
+
+        pAcc.reset();
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+bool Bitmap::Replace(const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount,
+                     sal_uInt8 const* pTols)
+{
+    // Bitmaps with 1 bit color depth can cause problems if they have other entries than black/white
+    // in their palette
+    if (GetBitCount() == 1)
+        Convert(BmpConversion::N4BitColors);
+
+    ScopedWriteAccess pAcc(*this);
+    bool bRet = false;
+
+    if (pAcc)
+    {
+        std::unique_ptr<long[]> pMinR(new long[nColorCount]);
+        std::unique_ptr<long[]> pMaxR(new long[nColorCount]);
+        std::unique_ptr<long[]> pMinG(new long[nColorCount]);
+        std::unique_ptr<long[]> pMaxG(new long[nColorCount]);
+        std::unique_ptr<long[]> pMinB(new long[nColorCount]);
+        std::unique_ptr<long[]> pMaxB(new long[nColorCount]);
+
+        if (pTols)
+        {
+            for (sal_uLong i = 0; i < nColorCount; i++)
+            {
+                const Color& rCol = pSearchColors[i];
+                const sal_uInt8 nTol = pTols[i];
+
+                pMinR[i] = MinMax<long>(rCol.GetRed() - nTol, 0, 255);
+                pMaxR[i] = MinMax<long>(rCol.GetRed() + nTol, 0, 255);
+                pMinG[i] = MinMax<long>(rCol.GetGreen() - nTol, 0, 255);
+                pMaxG[i] = MinMax<long>(rCol.GetGreen() + nTol, 0, 255);
+                pMinB[i] = MinMax<long>(rCol.GetBlue() - nTol, 0, 255);
+                pMaxB[i] = MinMax<long>(rCol.GetBlue() + nTol, 0, 255);
+            }
+        }
+        else
+        {
+            for (sal_uLong i = 0; i < nColorCount; i++)
+            {
+                const Color& rCol = pSearchColors[i];
+
+                pMinR[i] = rCol.GetRed();
+                pMaxR[i] = rCol.GetRed();
+                pMinG[i] = rCol.GetGreen();
+                pMaxG[i] = rCol.GetGreen();
+                pMinB[i] = rCol.GetBlue();
+                pMaxB[i] = rCol.GetBlue();
+            }
+        }
+
+        if (pAcc->HasPalette())
+        {
+            for (sal_uInt16 nEntry = 0, nPalCount = pAcc->GetPaletteEntryCount();
+                 nEntry < nPalCount; nEntry++)
+            {
+                const BitmapColor& rCol = pAcc->GetPaletteColor(nEntry);
+
+                for (sal_uLong i = 0; i < nColorCount; i++)
+                {
+                    if (pMinR[i] <= rCol.GetRed() && pMaxR[i] >= rCol.GetRed()
+                        && pMinG[i] <= rCol.GetGreen() && pMaxG[i] >= rCol.GetGreen()
+                        && pMinB[i] <= rCol.GetBlue() && pMaxB[i] >= rCol.GetBlue())
+                    {
+                        pAcc->SetPaletteColor(nEntry, pReplaceColors[i]);
+                        break;
+                    }
+                }
+            }
+        }
+        else
+        {
+            BitmapColor aCol;
+            std::unique_ptr<BitmapColor[]> pReplaces(new BitmapColor[nColorCount]);
+
+            for (sal_uLong i = 0; i < nColorCount; i++)
+                pReplaces[i] = pAcc->GetBestMatchingColor(pReplaceColors[i]);
+
+            for (long nY = 0, nHeight = pAcc->Height(); nY < nHeight; nY++)
+            {
+                Scanline pScanline = pAcc->GetScanline(nY);
+                for (long nX = 0, nWidth = pAcc->Width(); nX < nWidth; nX++)
+                {
+                    aCol = pAcc->GetPixelFromData(pScanline, nX);
+
+                    for (sal_uLong i = 0; i < nColorCount; i++)
+                    {
+                        if (pMinR[i] <= aCol.GetRed() && pMaxR[i] >= aCol.GetRed()
+                            && pMinG[i] <= aCol.GetGreen() && pMaxG[i] >= aCol.GetGreen()
+                            && pMinB[i] <= aCol.GetBlue() && pMaxB[i] >= aCol.GetBlue())
+                        {
+                            pAcc->SetPixelOnData(pScanline, nX, pReplaces[i]);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        pAcc.reset();
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+bool Bitmap::CombineSimple(const Bitmap& rMask, BmpCombine eCombine)
+{
+    ScopedReadAccess pMaskAcc(const_cast<Bitmap&>(rMask));
+    ScopedWriteAccess pAcc(*this);
+    bool bRet = false;
+
+    if (pMaskAcc && pAcc)
+    {
+        const long nWidth = std::min(pMaskAcc->Width(), pAcc->Width());
+        const long nHeight = std::min(pMaskAcc->Height(), pAcc->Height());
+        const Color aColBlack(COL_BLACK);
+        BitmapColor aPixel;
+        BitmapColor aMaskPixel;
+        const BitmapColor aWhite(pAcc->GetBestMatchingColor(COL_WHITE));
+        const BitmapColor aBlack(pAcc->GetBestMatchingColor(aColBlack));
+        const BitmapColor aMaskBlack(pMaskAcc->GetBestMatchingColor(aColBlack));
+
+        switch (eCombine)
+        {
+            case BmpCombine::And:
+            {
+                for (long nY = 0; nY < nHeight; nY++)
+                {
+                    Scanline pScanline = pAcc->GetScanline(nY);
+                    Scanline pScanlineMask = pMaskAcc->GetScanline(nY);
+                    for (long nX = 0; nX < nWidth; nX++)
+                    {
+                        if (pMaskAcc->GetPixelFromData(pScanlineMask, nX) != aMaskBlack
+                            && pAcc->GetPixelFromData(pScanline, nX) != aBlack)
+                        {
+                            pAcc->SetPixelOnData(pScanline, nX, aWhite);
+                        }
+                        else
+                        {
+                            pAcc->SetPixelOnData(pScanline, nX, aBlack);
+                        }
+                    }
+                }
+            }
+            break;
+
+            case BmpCombine::Or:
+            {
+                for (long nY = 0; nY < nHeight; nY++)
+                {
+                    Scanline pScanline = pAcc->GetScanline(nY);
+                    Scanline pScanlineMask = pMaskAcc->GetScanline(nY);
+                    for (long nX = 0; nX < nWidth; nX++)
+                    {
+                        if (pMaskAcc->GetPixelFromData(pScanlineMask, nX) != aMaskBlack
+                            || pAcc->GetPixelFromData(pScanline, nX) != aBlack)
+                        {
+                            pAcc->SetPixelOnData(pScanline, nX, aWhite);
+                        }
+                        else
+                        {
+                            pAcc->SetPixelOnData(pScanline, nX, aBlack);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+// TODO: Have a look at OutputDevice::ImplDrawAlpha() for some
+// optimizations. Might even consolidate the code here and there.
+bool Bitmap::Blend(const AlphaMask& rAlpha, const Color& rBackgroundColor)
+{
+    // Convert to a truecolor bitmap, if we're a paletted one. There's room for tradeoff decision here,
+    // maybe later for an overload (or a flag)
+    if (GetBitCount() <= 8)
+        Convert(BmpConversion::N24Bit);
+
+    AlphaMask::ScopedReadAccess pAlphaAcc(const_cast<AlphaMask&>(rAlpha));
+
+    ScopedWriteAccess pAcc(*this);
+    bool bRet = false;
+
+    if (pAlphaAcc && pAcc)
+    {
+        const long nWidth = std::min(pAlphaAcc->Width(), pAcc->Width());
+        const long nHeight = std::min(pAlphaAcc->Height(), pAcc->Height());
+
+        for (long nY = 0; nY < nHeight; ++nY)
+        {
+            Scanline pScanline = pAcc->GetScanline(nY);
+            Scanline pScanlineAlpha = pAlphaAcc->GetScanline(nY);
+            for (long nX = 0; nX < nWidth; ++nX)
+            {
+                pAcc->SetPixelOnData(
+                    pScanline, nX,
+                    pAcc->GetPixelFromData(pScanline, nX)
+                        .Merge(rBackgroundColor,
+                               255 - pAlphaAcc->GetIndexFromData(pScanlineAlpha, nX)));
+            }
+        }
+
+        bRet = true;
+    }
+
+    return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list