summaryrefslogtreecommitdiff
path: root/canvas/source/directx/dx_vcltools.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/directx/dx_vcltools.cxx')
-rwxr-xr-xcanvas/source/directx/dx_vcltools.cxx523
1 files changed, 523 insertions, 0 deletions
diff --git a/canvas/source/directx/dx_vcltools.cxx b/canvas/source/directx/dx_vcltools.cxx
new file mode 100755
index 000000000000..c48931b87eae
--- /dev/null
+++ b/canvas/source/directx/dx_vcltools.cxx
@@ -0,0 +1,523 @@
+/*************************************************************************
+ *
+ * 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_canvas.hxx"
+
+#include <vcl/canvastools.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "dx_impltools.hxx"
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <boost/scoped_array.hpp>
+
+#include "dx_vcltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ namespace
+ {
+ /// Calc number of colors in given BitmapInfoHeader
+ sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
+ {
+ if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
+ {
+ if( rBIH.biBitCount <= 8 )
+ {
+ if( rBIH.biClrUsed )
+ return rBIH.biClrUsed;
+ else
+ return 1L << rBIH.biBitCount;
+ }
+ }
+ else
+ {
+ BITMAPCOREHEADER* pCoreHeader = (BITMAPCOREHEADER*)&rBIH;
+
+ if( pCoreHeader->bcBitCount <= 8 )
+ return 1L << pCoreHeader->bcBitCount;
+ }
+
+ return 0; // nothing known
+ }
+
+ /// Draw DI bits to given Graphics
+ bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const void* hDIB )
+ {
+ bool bRet( false );
+ BitmapSharedPtr pBitmap;
+
+ const BITMAPINFO* pBI = (BITMAPINFO*)GlobalLock( (HGLOBAL)hDIB );
+
+ if( pBI )
+ {
+ const BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)pBI;
+ const BYTE* pBits = (BYTE*) pBI + *(DWORD*)pBI +
+ calcDIBColorCount( *pBIH ) * sizeof( RGBQUAD );
+
+ // forward to outsourced GDI+ rendering method
+ // (header clashes)
+ bRet = tools::drawDIBits( rGraphics, *pBI, (void*)pBits );
+
+ GlobalUnlock( (HGLOBAL)hDIB );
+ }
+
+ return bRet;
+ }
+
+ /** Draw VCL bitmap to given Graphics
+
+ @param rBmp
+ Reference to bitmap. Might get modified, in such a way
+ that it will hold a DIB after a successful function call.
+ */
+ bool drawVCLBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ ::Bitmap& rBmp )
+ {
+ BitmapSystemData aBmpSysData;
+
+ if( !rBmp.GetSystemData( aBmpSysData ) ||
+ !aBmpSysData.pDIB )
+ {
+ // first of all, ensure that Bitmap contains a DIB, by
+ // aquiring a read access
+ BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
+
+ // TODO(P2): Acquiring a read access can actually
+ // force a read from VRAM, thus, avoiding this
+ // step somehow will increase performance
+ // here.
+ if( pReadAcc )
+ {
+ // try again: now, WinSalBitmap must have
+ // generated a DIB
+ if( rBmp.GetSystemData( aBmpSysData ) &&
+ aBmpSysData.pDIB )
+ {
+ return drawDIBits( rGraphics,
+ aBmpSysData.pDIB );
+ }
+
+ rBmp.ReleaseAccess( pReadAcc );
+ }
+ }
+ else
+ {
+ return drawDIBits( rGraphics,
+ aBmpSysData.pDIB );
+ }
+
+ // failed to generate DIBits from vcl bitmap
+ return false;
+ }
+
+ /** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BbitmapEX
+ */
+ RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
+ {
+ // TODO(P2): Avoid temporary bitmap generation, maybe
+ // even ensure that created DIBs are copied back to
+ // BmpEx (currently, every AcquireReadAccess() will
+ // make the local bitmap copy unique, effectively
+ // duplicating the memory used)
+
+ ENSURE_OR_THROW( rBmpEx.IsTransparent(),
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "BmpEx not transparent" );
+
+ // convert transparent bitmap to 32bit RGBA
+ // ========================================
+
+ const ::Size aBmpSize( rBmpEx.GetSizePixel() );
+
+ RawRGBABitmap aBmpData;
+ aBmpData.mnWidth = aBmpSize.Width();
+ aBmpData.mnHeight = aBmpSize.Height();
+ aBmpData.mpBitmapData.reset( new sal_uInt8[ 4*aBmpData.mnWidth*aBmpData.mnHeight ] );
+
+ Bitmap aBitmap( rBmpEx.GetBitmap() );
+
+ ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
+ aBitmap );
+
+ const sal_Int32 nWidth( aBmpSize.Width() );
+ const sal_Int32 nHeight( aBmpSize.Height() );
+
+ ENSURE_OR_THROW( pReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to bitmap" );
+
+ if( rBmpEx.IsAlpha() )
+ {
+ Bitmap aAlpha( rBmpEx.GetAlpha().GetBitmap() );
+
+ ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.AcquireReadAccess(),
+ aAlpha );
+
+ // By convention, the access buffer always has
+ // one of the following formats:
+ //
+ // BMP_FORMAT_1BIT_MSB_PAL
+ // BMP_FORMAT_4BIT_MSN_PAL
+ // BMP_FORMAT_8BIT_PAL
+ // BMP_FORMAT_16BIT_TC_LSB_MASK
+ // BMP_FORMAT_24BIT_TC_BGR
+ // BMP_FORMAT_32BIT_TC_MASK
+ //
+ // and is always BMP_FORMAT_BOTTOM_UP
+ //
+ // This is the way
+ // WinSalBitmap::AcquireBuffer() sets up the
+ // buffer
+
+ ENSURE_OR_THROW( pAlphaReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to alpha" );
+
+ ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
+ pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unsupported alpha scanline format" );
+
+ BitmapColor aCol;
+ const sal_Int32 nWidth( aBmpSize.Width() );
+ const sal_Int32 nHeight( aBmpSize.Height() );
+ sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
+ int x, y;
+
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pReadAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ aCol = pReadAccess->GetPaletteColor( *pScan++ );
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ // store as RGBA
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ // TODO(P2): Might be advantageous
+ // to hand-formulate the following
+ // formats, too.
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_MASK:
+ {
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ // using fallback for those
+ // seldom formats
+ for( x=0; x<nWidth; ++x )
+ {
+ // yes. x and y are swapped on Get/SetPixel
+ aCol = pReadAccess->GetColor(y,x);
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_8BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_RGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ // FALLTHROUGH intended
+ default:
+ ENSURE_OR_THROW( false,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unexpected scanline format - has "
+ "WinSalBitmap::AcquireBuffer() changed?" );
+ }
+ }
+ }
+ else
+ {
+ Bitmap aMask( rBmpEx.GetMask() );
+
+ ScopedBitmapReadAccess pMaskReadAccess( aMask.AcquireReadAccess(),
+ aMask );
+
+ // By convention, the access buffer always has
+ // one of the following formats:
+ //
+ // BMP_FORMAT_1BIT_MSB_PAL
+ // BMP_FORMAT_4BIT_MSN_PAL
+ // BMP_FORMAT_8BIT_PAL
+ // BMP_FORMAT_16BIT_TC_LSB_MASK
+ // BMP_FORMAT_24BIT_TC_BGR
+ // BMP_FORMAT_32BIT_TC_MASK
+ //
+ // and is always BMP_FORMAT_BOTTOM_UP
+ //
+ // This is the way
+ // WinSalBitmap::AcquireBuffer() sets up the
+ // buffer
+
+ ENSURE_OR_THROW( pMaskReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to mask" );
+
+ ENSURE_OR_THROW( pMaskReadAccess->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unsupported mask scanline format" );
+
+ BitmapColor aCol;
+ int nCurrBit;
+ const int nMask( 1L );
+ const int nInitialBit(7);
+ sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
+ int x, y;
+
+ // mapping table, to get from mask index color to
+ // alpha value (which depends on the mask's palette)
+ sal_uInt8 aColorMap[2];
+
+ const BitmapColor& rCol0( pMaskReadAccess->GetPaletteColor( 0 ) );
+ const BitmapColor& rCol1( pMaskReadAccess->GetPaletteColor( 1 ) );
+
+ // shortcut for true luminance calculation
+ // (assumes that palette is grey-level). Note the
+ // swapped the indices here, to account for the
+ // fact that VCL's notion of alpha is inverted to
+ // the rest of the world's.
+ aColorMap[0] = rCol1.GetRed();
+ aColorMap[1] = rCol0.GetRed();
+
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pReadAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ aCol = pReadAccess->GetPaletteColor( *pScan++ );
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ // store as RGBA
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ // TODO(P2): Might be advantageous
+ // to hand-formulate the following
+ // formats, too.
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_MASK:
+ {
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ // using fallback for those
+ // seldom formats
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ // yes. x and y are swapped on Get/SetPixel
+ aCol = pReadAccess->GetColor(y,x);
+
+ // store as RGBA
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_8BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_RGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ // FALLTHROUGH intended
+ default:
+ ENSURE_OR_THROW( false,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unexpected scanline format - has "
+ "WinSalBitmap::AcquireBuffer() changed?" );
+ }
+ }
+ }
+
+ return aBmpData;
+ }
+
+ bool drawVCLBitmapEx( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const ::BitmapEx& rBmpEx )
+ {
+ if( !rBmpEx.IsTransparent() )
+ {
+ Bitmap aBmp( rBmpEx.GetBitmap() );
+ return drawVCLBitmap( rGraphics, aBmp );
+ }
+ else
+ {
+ return drawRGBABits( rGraphics,
+ bitmapFromVCLBitmapEx( rBmpEx ) );
+ }
+ }
+ }
+
+ bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ // TODO(F2): add support for floating point bitmap formats
+ uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
+ xBitmap, uno::UNO_QUERY );
+
+ if( !xIntBmp.is() )
+ return false;
+
+ ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
+ if( !aBmpEx )
+ return false;
+
+ return drawVCLBitmapEx( rGraphics, aBmpEx );
+ }
+ }
+}