summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/bmpfast.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi/bmpfast.cxx')
-rw-r--r--vcl/source/gdi/bmpfast.cxx986
1 files changed, 986 insertions, 0 deletions
diff --git a/vcl/source/gdi/bmpfast.cxx b/vcl/source/gdi/bmpfast.cxx
new file mode 100644
index 000000000000..4c9ab03ea9c1
--- /dev/null
+++ b/vcl/source/gdi/bmpfast.cxx
@@ -0,0 +1,986 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <vcl/bmpfast.hxx>
+
+#ifndef NO_OPTIMIZED_BITMAP_ACCESS
+
+#include <tools/debug.hxx>
+#include <vcl/bmpacc.hxx>
+
+#define FAST_ARGB_BGRA
+
+#include <stdlib.h>
+static bool bDisableFastBitops = (getenv( "SAL_DISABLE_BITMAPS_OPTS" ) != NULL);
+
+typedef unsigned char PIXBYTE;
+
+class BasePixelPtr
+{
+public:
+ BasePixelPtr( PIXBYTE* p = NULL ) : mpPixel( p ) {}
+ void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
+ PIXBYTE* GetRawPtr( void ) const { return mpPixel; }
+ void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
+ bool operator<( const BasePixelPtr& rCmp ) const { return (mpPixel < rCmp.mpPixel); }
+
+protected:
+ PIXBYTE* mpPixel;
+};
+
+template <ULONG PIXFMT>
+class TrueColorPixelPtr : public BasePixelPtr
+{
+public:
+ PIXBYTE GetRed() const;
+ PIXBYTE GetGreen() const;
+ PIXBYTE GetBlue() const;
+ PIXBYTE GetAlpha() const;
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const;
+ void SetAlpha( PIXBYTE a ) const;
+ void operator++(int);
+};
+
+// =======================================================================
+// template specializations for truecolor pixel formats
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 3; }
+
+ PIXBYTE GetRed() const { return mpPixel[0]; }
+ PIXBYTE GetGreen() const { return mpPixel[1]; }
+ PIXBYTE GetBlue() const { return mpPixel[2]; }
+ PIXBYTE GetAlpha() const { return 0; }
+ void SetAlpha( PIXBYTE ) const {}
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[0] = r;
+ mpPixel[1] = g;
+ mpPixel[2] = b;
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 3; }
+
+ PIXBYTE GetRed() const { return mpPixel[2]; }
+ PIXBYTE GetGreen() const { return mpPixel[1]; }
+ PIXBYTE GetBlue() const { return mpPixel[0]; }
+ PIXBYTE GetAlpha() const { return 0; }
+ void SetAlpha( PIXBYTE ) const {}
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[0] = b;
+ mpPixel[1] = g;
+ mpPixel[2] = r;
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 4; }
+
+ PIXBYTE GetRed() const { return mpPixel[1]; }
+ PIXBYTE GetGreen() const { return mpPixel[2]; }
+ PIXBYTE GetBlue() const { return mpPixel[3]; }
+ PIXBYTE GetAlpha() const { return mpPixel[0]; }
+ void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[1] = r;
+ mpPixel[2] = g;
+ mpPixel[3] = b;
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 4; }
+
+ PIXBYTE GetRed() const { return mpPixel[3]; }
+ PIXBYTE GetGreen() const { return mpPixel[2]; }
+ PIXBYTE GetBlue() const { return mpPixel[1]; }
+ PIXBYTE GetAlpha() const { return mpPixel[0]; }
+ void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[1] = b;
+ mpPixel[2] = g;
+ mpPixel[3] = r;
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 4; }
+
+ PIXBYTE GetRed() const { return mpPixel[0]; }
+ PIXBYTE GetGreen() const { return mpPixel[1]; }
+ PIXBYTE GetBlue() const { return mpPixel[2]; }
+ PIXBYTE GetAlpha() const { return mpPixel[3]; }
+ void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[0] = r;
+ mpPixel[1] = g;
+ mpPixel[2] = b;
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 4; }
+
+ PIXBYTE GetRed() const { return mpPixel[2]; }
+ PIXBYTE GetGreen() const { return mpPixel[1]; }
+ PIXBYTE GetBlue() const { return mpPixel[0]; }
+ PIXBYTE GetAlpha() const { return mpPixel[3]; }
+ void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[0] = b;
+ mpPixel[1] = g;
+ mpPixel[2] = r;
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 2; }
+
+ // TODO: non565-RGB
+ PIXBYTE GetRed() const { return (mpPixel[0] & 0xF8U); }
+ PIXBYTE GetGreen() const { return (mpPixel[0]<<5U) | ((mpPixel[1]>>3U)&28U); }
+ PIXBYTE GetBlue() const { return (mpPixel[1]<<3U); }
+ PIXBYTE GetAlpha() const { return 0; }
+ void SetAlpha( PIXBYTE ) const {}
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[0] = ((g >> 5U) & 7U) | (r & 0xF8U);
+ mpPixel[1] = ((g & 28U)<< 3U) | (b >> 3U);
+ }
+};
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 2; }
+
+ // TODO: non565-RGB
+ PIXBYTE GetRed() const { return (mpPixel[1] & 0xF8U); }
+ PIXBYTE GetGreen() const { return (mpPixel[1]<<5U) | ((mpPixel[0]>>3U)&28U); }
+ PIXBYTE GetBlue() const { return (mpPixel[0]<<3U); }
+ PIXBYTE GetAlpha() const { return 0; }
+ void SetAlpha( PIXBYTE ) const {}
+
+ void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
+ {
+ mpPixel[0] = ((g & 28U)<< 3U) | (b >> 3U);
+ mpPixel[1] = ((g >> 5U) & 7U) | (r & 0xF8U);
+ }
+};
+
+// -----------------------------------------------------------------------
+
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK> : public BasePixelPtr
+{
+public:
+ void operator++() { mpPixel += 1; }
+ PIXBYTE GetAlpha() const { return mpPixel[0]; }
+ void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
+ void SetColor( PIXBYTE, PIXBYTE, PIXBYTE ) const {}
+};
+
+// TODO: for some reason many Alpha maps are BMP_FORMAT_8BIT_PAL
+// they should be BMP_FORMAT_8BIT_TC_MASK
+template <>
+class TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL>
+: public TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK>
+{};
+
+// =======================================================================
+// converting truecolor formats
+
+template <ULONG SRCFMT, ULONG DSTFMT>
+inline void ImplConvertPixel( const TrueColorPixelPtr<DSTFMT>& rDst,
+ const TrueColorPixelPtr<SRCFMT>& rSrc )
+{
+ rDst.SetColor( rSrc.GetRed(), rSrc.GetGreen(), rSrc.GetBlue() );
+ rDst.SetAlpha( rSrc.GetAlpha() );
+}
+
+// -----------------------------------------------------------------------
+
+template <>
+inline void ImplConvertPixel<BMP_FORMAT_16BIT_TC_LSB_MASK, BMP_FORMAT_16BIT_TC_MSB_MASK> (
+ const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK>& rDst,
+ const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK>& rSrc )
+{
+ // byte swapping
+ const PIXBYTE* pSrc = rSrc.GetRawPtr();
+ PIXBYTE* pDst = rDst.GetRawPtr();
+ pDst[1] = pSrc[0];
+ pDst[0] = pSrc[1];
+}
+
+// -----------------------------------------------------------------------
+
+template <ULONG SRCFMT, ULONG DSTFMT>
+inline void ImplConvertLine( const TrueColorPixelPtr<DSTFMT>& rDst,
+ const TrueColorPixelPtr<SRCFMT>& rSrc, int nPixelCount )
+{
+ TrueColorPixelPtr<DSTFMT> aDst( rDst );
+ TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
+ while( --nPixelCount >= 0 )
+ {
+ ImplConvertPixel( aDst, aSrc );
+ ++aSrc;
+ ++aDst;
+ }
+}
+
+// =======================================================================
+// alpha blending truecolor pixels
+
+template <unsigned ALPHABITS, ULONG SRCFMT, ULONG DSTFMT>
+inline void ImplBlendPixels( const TrueColorPixelPtr<DSTFMT>& rDst,
+ const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal )
+{
+ if( !nAlphaVal )
+ ImplConvertPixel( rDst, rSrc );
+ else if( nAlphaVal != ~(~0 << ALPHABITS) )
+ {
+ static const unsigned nAlphaShift = (ALPHABITS > 8) ? 8 : ALPHABITS;
+ if( ALPHABITS > nAlphaShift )
+ nAlphaVal >>= ALPHABITS - nAlphaShift;
+
+ int nR = rDst.GetRed();
+ int nS = rSrc.GetRed();
+ nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift);
+
+ int nG = rDst.GetGreen();
+ nS = rSrc.GetGreen();
+ nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift);
+
+ int nB = rDst.GetBlue();
+ nS = rSrc.GetBlue();
+ nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift);
+
+ rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR),
+ sal::static_int_cast<PIXBYTE>(nG),
+ sal::static_int_cast<PIXBYTE>(nB) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+template <unsigned ALPHABITS, ULONG MASKFMT, ULONG SRCFMT, ULONG DSTFMT>
+inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
+ const TrueColorPixelPtr<SRCFMT>& rSrc, const TrueColorPixelPtr<MASKFMT>& rMsk,
+ int nPixelCount )
+{
+ TrueColorPixelPtr<MASKFMT> aMsk( rMsk );
+ TrueColorPixelPtr<DSTFMT> aDst( rDst );
+ TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
+ while( --nPixelCount >= 0 )
+ {
+ ImplBlendPixels<ALPHABITS>( aDst, aSrc, aMsk.GetAlpha() );
+ ++aDst;
+ ++aSrc;
+ ++aMsk;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+template <unsigned ALPHABITS, ULONG SRCFMT, ULONG DSTFMT>
+inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
+ const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal,
+ int nPixelCount )
+{
+ if( nAlphaVal == ~(~0 << ALPHABITS) )
+ ImplConvertLine( rDst, rSrc, nPixelCount );
+ else if( nAlphaVal )
+ {
+ TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
+ TrueColorPixelPtr<DSTFMT> aDst( rDst );
+ while( --nPixelCount >= 0 )
+ {
+ ImplBlendPixels<ALPHABITS>( aDst, aSrc, nAlphaVal );
+ ++aDst;
+ ++aSrc;
+ }
+ }
+}
+
+// =======================================================================
+
+static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
+{
+ const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
+ int nDstLinestep = rDstBuffer.mnScanlineSize;
+
+ const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
+ PIXBYTE* pRawDst = rDstBuffer.mpBits;
+
+ // source and destination don't match upside down
+ if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
+ {
+ pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
+ nDstLinestep = -rDstBuffer.mnScanlineSize;
+ }
+ else if( nSrcLinestep == nDstLinestep )
+ {
+ memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
+ return true;
+ }
+
+ int nByteWidth = nSrcLinestep;
+ if( nByteWidth > rDstBuffer.mnScanlineSize )
+ nByteWidth = rDstBuffer.mnScanlineSize;
+
+ for( int y = rSrcBuffer.mnHeight; --y >= 0; )
+ {
+ memcpy( pRawDst, pRawSrc, nByteWidth );
+ pRawSrc += nSrcLinestep;
+ pRawDst += nDstLinestep;
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------
+
+template <ULONG DSTFMT,ULONG SRCFMT>
+bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
+ BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
+{
+ // help the compiler to avoid instantiations of unneeded conversions
+ DBG_ASSERT( SRCFMT != DSTFMT, "ImplConvertToBitmap into same format");
+ if( SRCFMT == DSTFMT )
+ return false;
+
+ const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
+ int nDstLinestep = rDstBuffer.mnScanlineSize;
+
+ TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
+
+ // source and destination don't match upside down
+ if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
+ {
+ aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
+ nDstLinestep = -nDstLinestep;
+ }
+
+ for( int y = rSrcBuffer.mnHeight; --y >= 0; )
+ {
+ ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
+ rSrcLine.AddByteOffset( nSrcLinestep );
+ aDstLine.AddByteOffset( nDstLinestep );
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------
+
+template <ULONG SRCFMT>
+inline bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc )
+{
+ TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
+
+ // select the matching instantiation for the destination's bitmap format
+ switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
+ {
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ case BMP_FORMAT_8BIT_PAL:
+ break;
+
+ case BMP_FORMAT_8BIT_TC_MASK:
+// return ImplConvertToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc );
+ case BMP_FORMAT_24BIT_TC_MASK:
+// return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc );
+ case BMP_FORMAT_32BIT_TC_MASK:
+// return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc );
+ break;
+
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc );
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc );
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc );
+ case BMP_FORMAT_24BIT_TC_RGB:
+ return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc );
+
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc );
+#ifdef FAST_ARGB_BGRA
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc );
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc );
+#endif
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc );
+ }
+
+#ifdef DEBUG
+ static int nNotAccelerated = 0;
+ if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
+ if( ++nNotAccelerated == 100 )
+ {
+ int foo = 0; (void)foo; // so no warning is created when building on pro with debug
+ DBG_WARNING2( "ImplConvertFromBitmap for not accelerated case (0x%04X->0x%04X)",
+ rSrc.mnFormat, rDst.mnFormat );
+ }
+#endif
+
+ return false;
+}
+
+// =======================================================================
+
+// an universal stretching conversion is overkill in most common situations
+// => performance benefits for speeding up the non-stretching cases
+bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
+ const SalTwoRect& rTR )
+{
+ if( bDisableFastBitops )
+ return false;
+
+ // horizontal mirroring not implemented yet
+ if( rTR.mnDestWidth < 0 )
+ return false;
+ // vertical mirroring
+ if( rTR.mnDestHeight < 0 )
+ // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
+ return false;
+
+ // offseted conversion is not implemented yet
+ if( rTR.mnSrcX || rTR.mnSrcY )
+ return false;
+ if( rTR.mnDestX || rTR.mnDestY )
+ return false;
+
+ // stretched conversion is not implemented yet
+ if( rTR.mnDestWidth != rTR.mnSrcWidth )
+ return false;
+ if( rTR.mnDestHeight!= rTR.mnSrcHeight )
+ return false;
+
+ // check source image size
+ if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
+ return false;
+ if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
+ return false;
+
+ // check dest image size
+ if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
+ return false;
+ if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
+ return false;
+
+ const ULONG nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
+ const ULONG nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
+
+ // TODO: also implement conversions for 16bit colormasks with non-565 format
+ if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
+ if( rSrc.maColorMask.GetRedMask() != 0xF800
+ || rSrc.maColorMask.GetGreenMask()!= 0x07E0
+ || rSrc.maColorMask.GetBlueMask() != 0x001F )
+ return false;
+ if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
+ if( rDst.maColorMask.GetRedMask() != 0xF800
+ || rDst.maColorMask.GetGreenMask()!= 0x07E0
+ || rDst.maColorMask.GetBlueMask() != 0x001F )
+ return false;
+
+ // special handling of trivial cases
+ if( nSrcFormat == nDstFormat )
+ {
+ // accelerated palette conversions not yet implemented
+ if( rSrc.maPalette != rDst.maPalette )
+ return false;
+ return ImplCopyImage( rDst, rSrc );
+ }
+
+ // select the matching instantiation for the source's bitmap format
+ switch( nSrcFormat )
+ {
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ case BMP_FORMAT_8BIT_PAL:
+ break;
+
+ case BMP_FORMAT_8BIT_TC_MASK:
+// return ImplConvertFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
+ case BMP_FORMAT_24BIT_TC_MASK:
+// return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
+ case BMP_FORMAT_32BIT_TC_MASK:
+// return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
+ break;
+
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc );
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc );
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc );
+ case BMP_FORMAT_24BIT_TC_RGB:
+ return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc );
+
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc );
+#ifdef FAST_ARGB_BGRA
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc );
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc );
+#endif
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc );
+ }
+
+#ifdef DEBUG
+ static int nNotAccelerated = 0;
+ if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
+ {
+ if( ++nNotAccelerated == 100 )
+ {
+ int foo = 0; (void)foo; // so no warning is created when building on pro with debug
+ DBG_WARNING2( "ImplFastBitmapConversion for not accelerated case (0x%04X->0x%04X)", rSrc.mnFormat, rDst.mnFormat );
+ }
+ }
+#endif
+
+ return false;
+}
+
+// =======================================================================
+
+template <ULONG DSTFMT,ULONG SRCFMT> //,ULONG MSKFMT>
+bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
+ BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
+ const BitmapBuffer& rMskBuffer )
+{
+ //DBG_ASSERT( rMskBuffer.mnFormat == MSKFMT, "FastBmp BlendImage: wrong MSKFMT" );
+ DBG_ASSERT( rMskBuffer.mnFormat == BMP_FORMAT_8BIT_PAL, "FastBmp BlendImage: unusual MSKFMT" );
+
+ const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
+ int nMskLinestep = rMskBuffer.mnScanlineSize;
+ int nDstLinestep = rDstBuffer.mnScanlineSize;
+
+ TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
+ TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
+
+ // special case for single line masks
+ if( rMskBuffer.mnHeight == 1 )
+ nMskLinestep = 0;
+
+ // source and mask don't match: upside down
+ if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
+ {
+ aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
+ nMskLinestep = -nMskLinestep;
+ }
+
+ // source and destination don't match: upside down
+ if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
+ {
+ aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
+ nDstLinestep = -nDstLinestep;
+ }
+
+ for( int y = rSrcBuffer.mnHeight; --y >= 0; )
+ {
+ ImplBlendLines<8>( aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth );
+ aDstLine.AddByteOffset( nDstLinestep );
+ rSrcLine.AddByteOffset( nSrcLinestep );
+ aMskLine.AddByteOffset( nMskLinestep );
+ }
+
+ return true;
+}
+
+// some specializations to reduce the code size
+template <>
+inline bool ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR,BMP_FORMAT_24BIT_TC_BGR>(
+ TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR>&,
+ BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
+ const BitmapBuffer& rMskBuffer )
+ {
+ TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
+ return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
+ }
+
+template <>
+inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR,BMP_FORMAT_32BIT_TC_ABGR>(
+ TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR>&,
+ BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
+ const BitmapBuffer& rMskBuffer )
+ {
+ TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
+ return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
+ }
+
+template <>
+inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA,BMP_FORMAT_32BIT_TC_BGRA>(
+ TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA>&,
+ BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
+ const BitmapBuffer& rMskBuffer )
+ {
+ TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
+ return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
+ }
+
+// -----------------------------------------------------------------------
+
+template <ULONG SRCFMT>
+bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
+{
+ TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
+
+ // select the matching instantiation for the destination's bitmap format
+ switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
+ {
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ case BMP_FORMAT_8BIT_PAL:
+ break;
+
+ case BMP_FORMAT_8BIT_TC_MASK:
+// return ImplBlendToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
+ case BMP_FORMAT_24BIT_TC_MASK:
+// return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
+ case BMP_FORMAT_32BIT_TC_MASK:
+// return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
+ break;
+
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc, rMsk );
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc, rMsk );
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc, rMsk );
+ case BMP_FORMAT_24BIT_TC_RGB:
+ return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc, rMsk );
+
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc, rMsk );
+#ifdef FAST_ARGB_BGRA
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc, rMsk );
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc, rMsk );
+#endif
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc, rMsk );
+ }
+
+#ifdef DEBUG
+ static int nNotAccelerated = 0;
+ if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
+ if( ++nNotAccelerated == 100 )
+ {
+ int foo = 0; (void)foo; // so no warning is created when building on pro with debug
+ DBG_WARNING3( "ImplBlendFromBitmap for not accelerated case (0x%04X*0x%04X->0x%04X)",
+ rSrc.mnFormat, rMsk.mnFormat, rDst.mnFormat );
+ }
+#endif
+
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+bool ImplFastBitmapBlending( BitmapWriteAccess& rDstWA,
+ const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
+ const SalTwoRect& rTR )
+{
+ if( bDisableFastBitops )
+ return false;
+
+ // accelerated blending of paletted bitmaps not implemented yet
+ if( rSrcRA.HasPalette() )
+ return false;
+ if( rDstWA.HasPalette() )
+ return false;
+ // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
+
+ // horizontal mirroring not implemented yet
+ if( rTR.mnDestWidth < 0 )
+ return false;
+ // vertical mirroring
+ if( rTR.mnDestHeight < 0 )
+ // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
+ return false;
+
+ // offseted blending is not implemented yet
+ if( rTR.mnSrcX || rTR.mnSrcY )
+ return false;
+ if( rTR.mnDestX || rTR.mnDestY )
+ return false;
+
+ // stretched blending is not implemented yet
+ if( rTR.mnDestWidth != rTR.mnSrcWidth )
+ return false;
+ if( rTR.mnDestHeight!= rTR.mnSrcHeight )
+ return false;
+
+ // check source image size
+ if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
+ return false;
+ if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
+ return false;
+
+ // check mask image size
+ if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
+ return false;
+ if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
+ if( rMskRA.Height() != 1 )
+ return false;
+
+ // check dest image size
+ if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
+ return false;
+ if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
+ return false;
+
+ BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
+ const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
+ const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
+
+ const ULONG nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
+ const ULONG nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
+
+ // accelerated conversions for 16bit colormasks with non-565 format are not yet implemented
+ if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
+ if( rSrc.maColorMask.GetRedMask() != 0xF800
+ || rSrc.maColorMask.GetGreenMask()!= 0x07E0
+ || rSrc.maColorMask.GetBlueMask() != 0x001F)
+ return false;
+ if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
+ if( rDst.maColorMask.GetRedMask() != 0xF800
+ || rDst.maColorMask.GetGreenMask()!= 0x07E0
+ || rDst.maColorMask.GetBlueMask() != 0x001F)
+ return false;
+
+ // select the matching instantiation for the source's bitmap format
+ switch( nSrcFormat )
+ {
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ case BMP_FORMAT_8BIT_PAL:
+ break;
+
+ case BMP_FORMAT_8BIT_TC_MASK:
+// return ImplBlendFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
+ case BMP_FORMAT_24BIT_TC_MASK:
+// return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
+ case BMP_FORMAT_32BIT_TC_MASK:
+// return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
+ break;
+
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc, rMsk );
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc, rMsk );
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc, rMsk );
+ case BMP_FORMAT_24BIT_TC_RGB:
+ return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc, rMsk );
+
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc, rMsk );
+#ifdef FAST_ARGB_BGRA
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc, rMsk );
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc, rMsk );
+#endif
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc, rMsk );
+ }
+
+#ifdef DEBUG
+ static int nNotAccelerated = 0;
+ if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
+ if( ++nNotAccelerated == 100 )
+ {
+ int foo = 0; (void)foo; // so no warning is created when building on pro with debug
+ DBG_WARNING3( "ImplFastBlend for not accelerated case (0x%04X*0x%04X->0x%04X)",
+ rSrc.mnFormat, rMsk.mnFormat, rDst.mnFormat );
+ }
+#endif
+
+ return false;
+}
+
+bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
+{
+ if( bDisableFastBitops )
+ return false;
+
+ const ULONG nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
+
+ // erasing a bitmap is often just a byte-wise memory fill
+ bool bByteFill = true;
+ BYTE nFillByte;
+
+ switch( nDstFormat )
+ {
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ nFillByte = rColor.GetIndex();
+ nFillByte = static_cast<BYTE>( -(nFillByte & 1) ); // 0x00 or 0xFF
+ break;
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ nFillByte = rColor.GetIndex();
+ nFillByte &= 0x0F;
+ nFillByte |= (nFillByte << 4);
+ break;
+ case BMP_FORMAT_8BIT_PAL:
+ case BMP_FORMAT_8BIT_TC_MASK:
+ nFillByte = rColor.GetIndex();
+ break;
+
+ case BMP_FORMAT_24BIT_TC_MASK:
+ case BMP_FORMAT_24BIT_TC_BGR:
+ case BMP_FORMAT_24BIT_TC_RGB:
+ nFillByte = rColor.GetRed();
+ if( (nFillByte != rColor.GetGreen())
+ || (nFillByte != rColor.GetBlue()) )
+ bByteFill = false;
+ break;
+
+ default:
+ bByteFill = false;
+ nFillByte = 0x00;
+ break;
+ }
+
+ if( bByteFill )
+ {
+ long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
+ rtl_fillMemory( rDst.mpBits, nByteCount, nFillByte );
+ return true;
+ }
+
+ // TODO: handle other bitmap formats
+ switch( nDstFormat )
+ {
+ case BMP_FORMAT_32BIT_TC_MASK:
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ case BMP_FORMAT_24BIT_TC_RGB:
+
+ case BMP_FORMAT_32BIT_TC_ABGR:
+#ifdef FAST_ARGB_BGRA
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ case BMP_FORMAT_32BIT_TC_BGRA:
+#endif
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+// =======================================================================
+
+#else // NO_OPTIMIZED_BITMAP_ACCESS
+
+bool ImplFastBitmapConversion( BitmapBuffer&, const BitmapBuffer& )
+{
+ return false;
+}
+
+bool ImplFastBitmapBlending( BitmapWriteAccess&,
+ const BitmapReadAccess&, const BitmapReadAccess&,
+ const Size&, const Point& )
+{
+ return false;
+}
+
+bool ImplFastEraseBitmap( BitmapBuffer&, const BitmapColor& )
+{
+ return false;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */