CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / canvas / source / directx / dx_canvasbitmap.cxx
blobf15af7745422d003f8b44512e6d09061e5c9b0eb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
31 #include <ctype.h> // don't ask. msdev breaks otherwise...
32 #include <canvas/debug.hxx>
33 #include <canvas/canvastools.hxx>
34 #include <tools/diagnose_ex.h>
36 #include <vcl/bitmapex.hxx>
38 #include <boost/preprocessor/repetition.hpp>
39 #include <boost/preprocessor/iteration/local.hpp>
40 #include <boost/scoped_array.hpp>
42 #include "dx_canvasbitmap.hxx"
43 #include "dx_impltools.hxx"
46 using namespace ::com::sun::star;
48 namespace dxcanvas
50 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap,
51 const DeviceRef& rDevice ) :
52 mpDevice( rDevice ),
53 mpBitmap( rBitmap )
55 ENSURE_OR_THROW( mpDevice.is() && mpBitmap,
56 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
58 maCanvasHelper.setDevice( *mpDevice.get() );
59 maCanvasHelper.setTarget( mpBitmap );
62 void SAL_CALL CanvasBitmap::disposing()
64 mpBitmap.reset();
65 mpDevice.clear();
67 // forward to parent
68 CanvasBitmap_Base::disposing();
71 struct AlphaDIB
73 BITMAPINFOHEADER bmiHeader;
74 RGBQUAD bmiColors[256];
77 uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
79 uno::Any aRes;
80 // 0 ... get BitmapEx
81 // 1 ... get Pixbuf with bitmap RGB content
82 // 2 ... get Pixbuf with bitmap alpha mask
83 switch( nHandle )
85 // sorry, no BitmapEx here...
86 case 0:
87 aRes = ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
88 break;
90 case 1:
92 if(!mpBitmap->hasAlpha())
94 HBITMAP aHBmp;
95 mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp );
97 uno::Sequence< uno::Any > args(1);
98 args[0] = uno::Any( sal_Int64(aHBmp) );
100 aRes <<= args;
102 else
104 // need to copy&convert the bitmap, since dx
105 // canvas uses inline alpha channel
106 HDC hScreenDC=GetDC(NULL);
107 const basegfx::B2IVector aSize(mpBitmap->getSize());
108 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
109 aSize.getX(),
110 aSize.getY() );
111 if( !hBmpBitmap )
112 return aRes;
114 BITMAPINFOHEADER aBIH;
116 aBIH.biSize = sizeof( BITMAPINFOHEADER );
117 aBIH.biWidth = aSize.getX();
118 aBIH.biHeight = -aSize.getY();
119 aBIH.biPlanes = 1;
120 aBIH.biBitCount = 32;
121 aBIH.biCompression = BI_RGB; // expects pixel in
122 // bbggrrxx format
123 // (little endian)
124 aBIH.biSizeImage = 0;
125 aBIH.biXPelsPerMeter = 0;
126 aBIH.biYPelsPerMeter = 0;
127 aBIH.biClrUsed = 0;
128 aBIH.biClrImportant = 0;
130 Gdiplus::BitmapData aBmpData;
131 aBmpData.Width = aSize.getX();
132 aBmpData.Height = aSize.getY();
133 aBmpData.Stride = 4*aBmpData.Width;
134 aBmpData.PixelFormat = PixelFormat32bppARGB;
135 aBmpData.Scan0 = NULL;
136 const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
137 BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
138 if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
139 Gdiplus::ImageLockModeRead,
140 PixelFormat32bppARGB, // outputs ARGB (big endian)
141 &aBmpData ) )
143 // failed to lock, bail out
144 return aRes;
147 // now aBmpData.Scan0 contains our bits - push
148 // them into HBITMAP, ignoring alpha
149 SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS );
151 pGDIPlusBitmap->UnlockBits( &aBmpData );
153 uno::Sequence< uno::Any > args(1);
154 args[0] = uno::Any( sal_Int64(hBmpBitmap) );
156 aRes <<= args;
159 break;
161 case 2:
163 if(!mpBitmap->hasAlpha())
165 return aRes;
167 else
169 static AlphaDIB aDIB=
171 {0,0,0,1,8,BI_RGB,0,0,0,0,0},
173 // this here fills palette with grey
174 // level colors, starting from 0,0,0
175 // up to 255,255,255
176 #define BOOST_PP_LOCAL_MACRO(n_) \
177 BOOST_PP_COMMA_IF(n_) \
178 {n_,n_,n_,n_}
179 #define BOOST_PP_LOCAL_LIMITS (0, 255)
180 #include BOOST_PP_LOCAL_ITERATE()
184 // need to copy&convert the bitmap, since dx
185 // canvas uses inline alpha channel
186 HDC hScreenDC=GetDC(NULL);
187 const basegfx::B2IVector aSize(mpBitmap->getSize());
188 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() );
189 if( !hBmpBitmap )
190 return aRes;
192 aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
193 aDIB.bmiHeader.biWidth = aSize.getX();
194 aDIB.bmiHeader.biHeight = -aSize.getY();
195 aDIB.bmiHeader.biPlanes = 1;
196 aDIB.bmiHeader.biBitCount = 8;
197 aDIB.bmiHeader.biCompression = BI_RGB;
198 aDIB.bmiHeader.biSizeImage = 0;
199 aDIB.bmiHeader.biXPelsPerMeter = 0;
200 aDIB.bmiHeader.biYPelsPerMeter = 0;
201 aDIB.bmiHeader.biClrUsed = 0;
202 aDIB.bmiHeader.biClrImportant = 0;
204 Gdiplus::BitmapData aBmpData;
205 aBmpData.Width = aSize.getX();
206 aBmpData.Height = aSize.getY();
207 aBmpData.Stride = 4*aBmpData.Width;
208 aBmpData.PixelFormat = PixelFormat32bppARGB;
209 aBmpData.Scan0 = NULL;
210 const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
211 BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
212 if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
213 Gdiplus::ImageLockModeRead,
214 PixelFormat32bppARGB, // outputs ARGB (big endian)
215 &aBmpData ) )
217 // failed to lock, bail out
218 return aRes;
221 // copy only alpha channel to pAlphaBits
222 const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3);
223 boost::scoped_array<sal_uInt8> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] );
224 const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0;
225 pInBits+=3;
226 sal_uInt8* pOutBits;
227 for( sal_Int32 y=0; y<aSize.getY(); ++y )
229 pOutBits=pAlphaBits.get()+y*nScanWidth;
230 for( sal_Int32 x=0; x<aSize.getX(); ++x )
232 *pOutBits++ = 255-*pInBits;
233 pInBits += 4;
237 pGDIPlusBitmap->UnlockBits( &aBmpData );
239 // set bits to newly create HBITMAP
240 SetDIBits( hScreenDC, hBmpBitmap, 0,
241 aSize.getY(), pAlphaBits.get(),
242 (PBITMAPINFO)&aDIB, DIB_RGB_COLORS );
244 uno::Sequence< uno::Any > args(1);
245 args[0] = uno::Any( sal_Int64(hBmpBitmap) );
247 aRes <<= args;
250 break;
253 return aRes;
256 #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap"
257 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
259 ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
261 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
264 sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
266 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
269 uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
271 uno::Sequence< ::rtl::OUString > aRet(1);
272 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
274 return aRet;