From ead48306fdb7bd8efd07c9066c71dd5aeb38fdbc Mon Sep 17 00:00:00 2001 From: Kurt Zenker Date: Tue, 24 Jun 2008 09:31:46 +0000 Subject: [PATCH] INTEGRATION: CWS canvas05 (1.2.2); FILE MERGED 2008/04/21 07:29:51 thb 1.2.2.5: RESYNC: (1.2-1.3); FILE MERGED 2008/04/06 23:48:37 thb 1.2.2.4: Fixing build breakage under Win32 2008/04/04 09:00:13 thb 1.2.2.3: Merging emf+ changes for dx canvas 2008/01/22 00:25:23 thb 1.2.2.2: #i81092# Making gdiplus and dx canvas more independent 2007/12/20 22:18:57 thb 1.2.2.1: #i81092# #i78888# #i78925# #i79258# #i79437# #i84784# Large canvas rework, completing various areas such as color spaces, bitmap data access, true sprite and non-sprite implementations, and upstreaming the canvas parts of rodos emf+ rendering --- canvas/source/directx/dx_canvasbitmap.cxx | 212 +++++++++++++++++++++- 1 file changed, 203 insertions(+), 9 deletions(-) diff --git a/canvas/source/directx/dx_canvasbitmap.cxx b/canvas/source/directx/dx_canvasbitmap.cxx index 6b7fc85408b0..5e4b61e6d104 100755 --- a/canvas/source/directx/dx_canvasbitmap.cxx +++ b/canvas/source/directx/dx_canvasbitmap.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dx_canvasbitmap.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.4 $ * * This file is part of OpenOffice.org. * @@ -28,9 +28,19 @@ * ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_canvas.hxx" + #include // don't ask. msdev breaks otherwise... #include #include +#include + +#include + +#include +#include +#include #include "dx_canvasbitmap.hxx" #include "dx_impltools.hxx" @@ -40,28 +50,212 @@ using namespace ::com::sun::star; namespace dxcanvas { - CanvasBitmap::CanvasBitmap( const DXBitmapSharedPtr& rSurface, - const DeviceRef& rDevice ) : + CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap, + const DeviceRef& rDevice ) : mpDevice( rDevice ), - mpSurface( rSurface ) + mpBitmap( rBitmap ) { - ENSURE_AND_THROW( mpDevice.is() && rSurface, - "CanvasBitmap::CanvasBitmap(): Invalid surface or device" ); + ENSURE_OR_THROW( mpDevice.is() && mpBitmap, + "CanvasBitmap::CanvasBitmap(): Invalid surface or device" ); maCanvasHelper.setDevice( *mpDevice.get() ); - maCanvasHelper.setTarget( rSurface, - ::basegfx::B2ISize() ); + maCanvasHelper.setTarget( mpBitmap ); } void SAL_CALL CanvasBitmap::disposing() { - mpSurface.reset(); + mpBitmap.reset(); mpDevice.clear(); // forward to parent CanvasBitmap_Base::disposing(); } + struct AlphaDIB + { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[256]; + }; + + uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException) + { + uno::Any aRes; + // 0 ... get BitmapEx + // 1 ... get Pixbuf with bitmap RGB content + // 2 ... get Pixbuf with bitmap alpha mask + switch( nHandle ) + { + // sorry, no BitmapEx here... + case 0: + aRes = ::com::sun::star::uno::Any( reinterpret_cast( (BitmapEx*) NULL ) ); + break; + + case 1: + { + if(!mpBitmap->hasAlpha()) + { + HBITMAP aHBmp; + mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp ); + + uno::Sequence< uno::Any > args(1); + args[0] = uno::Any( sal_Int64(aHBmp) ); + + aRes <<= args; + } + else + { + // need to copy&convert the bitmap, since dx + // canvas uses inline alpha channel + HDC hScreenDC=GetDC(NULL); + const basegfx::B2IVector aSize(mpBitmap->getSize()); + HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, + aSize.getX(), + aSize.getY() ); + if( !hBmpBitmap ) + return aRes; + + BITMAPINFOHEADER aBIH; + + aBIH.biSize = sizeof( BITMAPINFOHEADER ); + aBIH.biWidth = aSize.getX(); + aBIH.biHeight = -aSize.getY(); + aBIH.biPlanes = 1; + aBIH.biBitCount = 32; + aBIH.biCompression = BI_RGB; // expects pixel in + // bbggrrxx format + // (little endian) + aBIH.biSizeImage = 0; + aBIH.biXPelsPerMeter = 0; + aBIH.biYPelsPerMeter = 0; + aBIH.biClrUsed = 0; + aBIH.biClrImportant = 0; + + Gdiplus::BitmapData aBmpData; + aBmpData.Width = aSize.getX(); + aBmpData.Height = aSize.getY(); + aBmpData.Stride = 4*aBmpData.Width; + aBmpData.PixelFormat = PixelFormat32bppARGB; + aBmpData.Scan0 = NULL; + const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() ); + BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap(); + if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect, + Gdiplus::ImageLockModeRead, + PixelFormat32bppARGB, // outputs ARGB (big endian) + &aBmpData ) ) + { + // failed to lock, bail out + return aRes; + } + + // now aBmpData.Scan0 contains our bits - push + // them into HBITMAP, ignoring alpha + SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS ); + + pGDIPlusBitmap->UnlockBits( &aBmpData ); + + uno::Sequence< uno::Any > args(1); + args[0] = uno::Any( sal_Int64(hBmpBitmap) ); + + aRes <<= args; + } + } + break; + + case 2: + { + if(!mpBitmap->hasAlpha()) + { + return aRes; + } + else + { + static AlphaDIB aDIB= + { + {0,0,0,1,8,BI_RGB,0,0,0,0,0}, + { + // this here fills palette with grey + // level colors, starting from 0,0,0 + // up to 255,255,255 +#define BOOST_PP_LOCAL_MACRO(n_) \ + BOOST_PP_COMMA_IF(n_) \ + {n_,n_,n_,n_} +#define BOOST_PP_LOCAL_LIMITS (0, 255) +#include BOOST_PP_LOCAL_ITERATE() + } + }; + + // need to copy&convert the bitmap, since dx + // canvas uses inline alpha channel + HDC hScreenDC=GetDC(NULL); + const basegfx::B2IVector aSize(mpBitmap->getSize()); + HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() ); + if( !hBmpBitmap ) + return aRes; + + aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + aDIB.bmiHeader.biWidth = aSize.getX(); + aDIB.bmiHeader.biHeight = -aSize.getY(); + aDIB.bmiHeader.biPlanes = 1; + aDIB.bmiHeader.biBitCount = 8; + aDIB.bmiHeader.biCompression = BI_RGB; + aDIB.bmiHeader.biSizeImage = 0; + aDIB.bmiHeader.biXPelsPerMeter = 0; + aDIB.bmiHeader.biYPelsPerMeter = 0; + aDIB.bmiHeader.biClrUsed = 0; + aDIB.bmiHeader.biClrImportant = 0; + + Gdiplus::BitmapData aBmpData; + aBmpData.Width = aSize.getX(); + aBmpData.Height = aSize.getY(); + aBmpData.Stride = 4*aBmpData.Width; + aBmpData.PixelFormat = PixelFormat32bppARGB; + aBmpData.Scan0 = NULL; + const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() ); + BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap(); + if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect, + Gdiplus::ImageLockModeRead, + PixelFormat32bppARGB, // outputs ARGB (big endian) + &aBmpData ) ) + { + // failed to lock, bail out + return aRes; + } + + // copy only alpha channel to pAlphaBits + const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3); + boost::scoped_array pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] ); + const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0; + pInBits+=3; + sal_uInt8* pOutBits; + for( sal_Int32 y=0; yUnlockBits( &aBmpData ); + + // set bits to newly create HBITMAP + SetDIBits( hScreenDC, hBmpBitmap, 0, + aSize.getY(), pAlphaBits.get(), + (PBITMAPINFO)&aDIB, DIB_RGB_COLORS ); + + uno::Sequence< uno::Any > args(1); + args[0] = uno::Any( sal_Int64(hBmpBitmap) ); + + aRes <<= args; + } + } + break; + } + + return aRes; + } + #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap" #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"