1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dx_canvasbitmap.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <ctype.h> // don't ask. msdev breaks otherwise...
35 #include <canvas/debug.hxx>
36 #include <canvas/canvastools.hxx>
37 #include <tools/diagnose_ex.h>
39 #include <vcl/bitmapex.hxx>
41 #include <boost/preprocessor/repetition.hpp>
42 #include <boost/preprocessor/iteration/local.hpp>
43 #include <boost/scoped_array.hpp>
45 #include "dx_canvasbitmap.hxx"
46 #include "dx_impltools.hxx"
49 using namespace ::com::sun::star
;
53 CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr
& rBitmap
,
54 const DeviceRef
& rDevice
) :
58 ENSURE_OR_THROW( mpDevice
.is() && mpBitmap
,
59 "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
61 maCanvasHelper
.setDevice( *mpDevice
.get() );
62 maCanvasHelper
.setTarget( mpBitmap
);
65 void SAL_CALL
CanvasBitmap::disposing()
71 CanvasBitmap_Base::disposing();
76 BITMAPINFOHEADER bmiHeader
;
77 RGBQUAD bmiColors
[256];
80 uno::Any SAL_CALL
CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle
) throw (uno::RuntimeException
)
84 // 1 ... get Pixbuf with bitmap RGB content
85 // 2 ... get Pixbuf with bitmap alpha mask
88 // sorry, no BitmapEx here...
90 aRes
= ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64
>( (BitmapEx
*) NULL
) );
95 if(!mpBitmap
->hasAlpha())
98 mpBitmap
->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp
);
100 uno::Sequence
< uno::Any
> args(1);
101 args
[0] = uno::Any( sal_Int64(aHBmp
) );
107 // need to copy&convert the bitmap, since dx
108 // canvas uses inline alpha channel
109 HDC hScreenDC
=GetDC(NULL
);
110 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
111 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
,
117 BITMAPINFOHEADER aBIH
;
119 aBIH
.biSize
= sizeof( BITMAPINFOHEADER
);
120 aBIH
.biWidth
= aSize
.getX();
121 aBIH
.biHeight
= -aSize
.getY();
123 aBIH
.biBitCount
= 32;
124 aBIH
.biCompression
= BI_RGB
; // expects pixel in
127 aBIH
.biSizeImage
= 0;
128 aBIH
.biXPelsPerMeter
= 0;
129 aBIH
.biYPelsPerMeter
= 0;
131 aBIH
.biClrImportant
= 0;
133 Gdiplus::BitmapData aBmpData
;
134 aBmpData
.Width
= aSize
.getX();
135 aBmpData
.Height
= aSize
.getY();
136 aBmpData
.Stride
= 4*aBmpData
.Width
;
137 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
138 aBmpData
.Scan0
= NULL
;
139 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
140 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
141 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
142 Gdiplus::ImageLockModeRead
,
143 PixelFormat32bppARGB
, // outputs ARGB (big endian)
146 // failed to lock, bail out
150 // now aBmpData.Scan0 contains our bits - push
151 // them into HBITMAP, ignoring alpha
152 SetDIBits( hScreenDC
, hBmpBitmap
, 0, aSize
.getY(), aBmpData
.Scan0
, (PBITMAPINFO
)&aBIH
, DIB_RGB_COLORS
);
154 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
156 uno::Sequence
< uno::Any
> args(1);
157 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
166 if(!mpBitmap
->hasAlpha())
172 static AlphaDIB aDIB
=
174 {0,0,0,1,8,BI_RGB
,0,0,0,0,0},
176 // this here fills palette with grey
177 // level colors, starting from 0,0,0
179 #define BOOST_PP_LOCAL_MACRO(n_) \
180 BOOST_PP_COMMA_IF(n_) \
182 #define BOOST_PP_LOCAL_LIMITS (0, 255)
183 #include BOOST_PP_LOCAL_ITERATE()
187 // need to copy&convert the bitmap, since dx
188 // canvas uses inline alpha channel
189 HDC hScreenDC
=GetDC(NULL
);
190 const basegfx::B2IVector
aSize(mpBitmap
->getSize());
191 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
, aSize
.getX(), aSize
.getY() );
195 aDIB
.bmiHeader
.biSize
= sizeof( BITMAPINFOHEADER
);
196 aDIB
.bmiHeader
.biWidth
= aSize
.getX();
197 aDIB
.bmiHeader
.biHeight
= -aSize
.getY();
198 aDIB
.bmiHeader
.biPlanes
= 1;
199 aDIB
.bmiHeader
.biBitCount
= 8;
200 aDIB
.bmiHeader
.biCompression
= BI_RGB
;
201 aDIB
.bmiHeader
.biSizeImage
= 0;
202 aDIB
.bmiHeader
.biXPelsPerMeter
= 0;
203 aDIB
.bmiHeader
.biYPelsPerMeter
= 0;
204 aDIB
.bmiHeader
.biClrUsed
= 0;
205 aDIB
.bmiHeader
.biClrImportant
= 0;
207 Gdiplus::BitmapData aBmpData
;
208 aBmpData
.Width
= aSize
.getX();
209 aBmpData
.Height
= aSize
.getY();
210 aBmpData
.Stride
= 4*aBmpData
.Width
;
211 aBmpData
.PixelFormat
= PixelFormat32bppARGB
;
212 aBmpData
.Scan0
= NULL
;
213 const Gdiplus::Rect
aRect( 0,0,aSize
.getX(),aSize
.getY() );
214 BitmapSharedPtr pGDIPlusBitmap
=mpBitmap
->getBitmap();
215 if( Gdiplus::Ok
!= pGDIPlusBitmap
->LockBits( &aRect
,
216 Gdiplus::ImageLockModeRead
,
217 PixelFormat32bppARGB
, // outputs ARGB (big endian)
220 // failed to lock, bail out
224 // copy only alpha channel to pAlphaBits
225 const sal_Int32
nScanWidth((aSize
.getX() + 3) & ~3);
226 boost::scoped_array
<sal_uInt8
> pAlphaBits( new sal_uInt8
[nScanWidth
*aSize
.getY()] );
227 const sal_uInt8
* pInBits
=(sal_uInt8
*)aBmpData
.Scan0
;
230 for( sal_Int32 y
=0; y
<aSize
.getY(); ++y
)
232 pOutBits
=pAlphaBits
.get()+y
*nScanWidth
;
233 for( sal_Int32 x
=0; x
<aSize
.getX(); ++x
)
235 *pOutBits
++ = 255-*pInBits
;
240 pGDIPlusBitmap
->UnlockBits( &aBmpData
);
242 // set bits to newly create HBITMAP
243 SetDIBits( hScreenDC
, hBmpBitmap
, 0,
244 aSize
.getY(), pAlphaBits
.get(),
245 (PBITMAPINFO
)&aDIB
, DIB_RGB_COLORS
);
247 uno::Sequence
< uno::Any
> args(1);
248 args
[0] = uno::Any( sal_Int64(hBmpBitmap
) );
259 #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap"
260 #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
262 ::rtl::OUString SAL_CALL
CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException
)
264 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME
) );
267 sal_Bool SAL_CALL
CanvasBitmap::supportsService( const ::rtl::OUString
& ServiceName
) throw (uno::RuntimeException
)
269 return ServiceName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME
) );
272 uno::Sequence
< ::rtl::OUString
> SAL_CALL
CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException
)
274 uno::Sequence
< ::rtl::OUString
> aRet(1);
275 aRet
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME
) );