Branch libreoffice-5-0-4
[LibreOffice.git] / canvas / source / directx / dx_canvasbitmap.cxx
blob952661542111d3cce7fceacf92cbf796734c001a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <ctype.h>
22 #include <canvas/debug.hxx>
23 #include <canvas/canvastools.hxx>
24 #include <cppuhelper/supportsservice.hxx>
25 #include <tools/diagnose_ex.h>
27 #include <vcl/bitmapex.hxx>
29 #include <boost/preprocessor/repetition.hpp>
30 #include <boost/preprocessor/iteration/local.hpp>
31 #include <boost/scoped_array.hpp>
33 #include "dx_canvasbitmap.hxx"
34 #include "dx_impltools.hxx"
37 using namespace ::com::sun::star;
39 namespace dxcanvas
41 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap,
42 const DeviceRef& rDevice ) :
43 mpDevice( rDevice ),
44 mpBitmap( rBitmap )
46 ENSURE_OR_THROW( mpDevice.is() && mpBitmap,
47 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
49 maCanvasHelper.setDevice( *mpDevice.get() );
50 maCanvasHelper.setTarget( mpBitmap );
53 void CanvasBitmap::disposeThis()
55 mpBitmap.reset();
56 mpDevice.clear();
58 // forward to parent
59 CanvasBitmap_Base::disposeThis();
62 struct AlphaDIB
64 BITMAPINFOHEADER bmiHeader;
65 RGBQUAD bmiColors[256];
68 uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
70 uno::Any aRes;
71 // 0 ... get BitmapEx
72 // 1 ... get Pixbuf with bitmap RGB content
73 // 2 ... get Pixbuf with bitmap alpha mask
74 switch( nHandle )
76 // sorry, no BitmapEx here...
77 case 0:
78 aRes = ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
79 break;
81 case 1:
83 if(!mpBitmap->hasAlpha())
85 HBITMAP aHBmp;
86 mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp );
88 uno::Sequence< uno::Any > args(1);
89 args[0] = uno::Any( sal_Int64(aHBmp) );
91 aRes <<= args;
93 else
95 // need to copy&convert the bitmap, since dx
96 // canvas uses inline alpha channel
97 HDC hScreenDC=GetDC(NULL);
98 const basegfx::B2IVector aSize(mpBitmap->getSize());
99 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
100 aSize.getX(),
101 aSize.getY() );
102 if( !hBmpBitmap )
103 return aRes;
105 BITMAPINFOHEADER aBIH;
107 aBIH.biSize = sizeof( BITMAPINFOHEADER );
108 aBIH.biWidth = aSize.getX();
109 aBIH.biHeight = -aSize.getY();
110 aBIH.biPlanes = 1;
111 aBIH.biBitCount = 32;
112 aBIH.biCompression = BI_RGB; // expects pixel in
113 // bbggrrxx format
114 // (little endian)
115 aBIH.biSizeImage = 0;
116 aBIH.biXPelsPerMeter = 0;
117 aBIH.biYPelsPerMeter = 0;
118 aBIH.biClrUsed = 0;
119 aBIH.biClrImportant = 0;
121 Gdiplus::BitmapData aBmpData;
122 aBmpData.Width = aSize.getX();
123 aBmpData.Height = aSize.getY();
124 aBmpData.Stride = 4*aBmpData.Width;
125 aBmpData.PixelFormat = PixelFormat32bppARGB;
126 aBmpData.Scan0 = NULL;
127 const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
128 BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
129 if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
130 Gdiplus::ImageLockModeRead,
131 PixelFormat32bppARGB, // outputs ARGB (big endian)
132 &aBmpData ) )
134 // failed to lock, bail out
135 return aRes;
138 // now aBmpData.Scan0 contains our bits - push
139 // them into HBITMAP, ignoring alpha
140 SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS );
142 pGDIPlusBitmap->UnlockBits( &aBmpData );
144 uno::Sequence< uno::Any > args(1);
145 args[0] = uno::Any( sal_Int64(hBmpBitmap) );
147 aRes <<= args;
150 break;
152 case 2:
154 if(!mpBitmap->hasAlpha())
156 return aRes;
158 else
160 static AlphaDIB aDIB=
162 {0,0,0,1,8,BI_RGB,0,0,0,0,0},
164 // this here fills palette with grey
165 // level colors, starting from 0,0,0
166 // up to 255,255,255
167 #define BOOST_PP_LOCAL_MACRO(n_) \
168 BOOST_PP_COMMA_IF(n_) \
169 {n_,n_,n_,n_}
170 #define BOOST_PP_LOCAL_LIMITS (0, 255)
171 #include BOOST_PP_LOCAL_ITERATE()
175 // need to copy&convert the bitmap, since dx
176 // canvas uses inline alpha channel
177 HDC hScreenDC=GetDC(NULL);
178 const basegfx::B2IVector aSize(mpBitmap->getSize());
179 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() );
180 if( !hBmpBitmap )
181 return aRes;
183 aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
184 aDIB.bmiHeader.biWidth = aSize.getX();
185 aDIB.bmiHeader.biHeight = -aSize.getY();
186 aDIB.bmiHeader.biPlanes = 1;
187 aDIB.bmiHeader.biBitCount = 8;
188 aDIB.bmiHeader.biCompression = BI_RGB;
189 aDIB.bmiHeader.biSizeImage = 0;
190 aDIB.bmiHeader.biXPelsPerMeter = 0;
191 aDIB.bmiHeader.biYPelsPerMeter = 0;
192 aDIB.bmiHeader.biClrUsed = 0;
193 aDIB.bmiHeader.biClrImportant = 0;
195 Gdiplus::BitmapData aBmpData;
196 aBmpData.Width = aSize.getX();
197 aBmpData.Height = aSize.getY();
198 aBmpData.Stride = 4*aBmpData.Width;
199 aBmpData.PixelFormat = PixelFormat32bppARGB;
200 aBmpData.Scan0 = NULL;
201 const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
202 BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
203 if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
204 Gdiplus::ImageLockModeRead,
205 PixelFormat32bppARGB, // outputs ARGB (big endian)
206 &aBmpData ) )
208 // failed to lock, bail out
209 return aRes;
212 // copy only alpha channel to pAlphaBits
213 const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3);
214 boost::scoped_array<sal_uInt8> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] );
215 const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0;
216 pInBits+=3;
217 for( sal_Int32 y=0; y<aSize.getY(); ++y )
219 sal_uInt8* pOutBits=pAlphaBits.get()+y*nScanWidth;
220 for( sal_Int32 x=0; x<aSize.getX(); ++x )
222 *pOutBits++ = 255-*pInBits;
223 pInBits += 4;
227 pGDIPlusBitmap->UnlockBits( &aBmpData );
229 // set bits to newly create HBITMAP
230 SetDIBits( hScreenDC, hBmpBitmap, 0,
231 aSize.getY(), pAlphaBits.get(),
232 (PBITMAPINFO)&aDIB, DIB_RGB_COLORS );
234 uno::Sequence< uno::Any > args(1);
235 args[0] = uno::Any( sal_Int64(hBmpBitmap) );
237 aRes <<= args;
240 break;
243 return aRes;
246 OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
248 return OUString( "DXCanvas.CanvasBitmap" );
251 sal_Bool SAL_CALL CanvasBitmap::supportsService( const OUString& ServiceName ) throw (uno::RuntimeException)
253 return cppu::supportsService( this, ServiceName );
256 uno::Sequence< OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
258 uno::Sequence< OUString > aRet(1);
259 aRet[0] = "com.sun.star.rendering.CanvasBitmap";
261 return aRet;
266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */